日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CodeForces - 1196F K-th Path(最短路+思维)好题

發布時間:2024/4/11 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CodeForces - 1196F K-th Path(最短路+思维)好题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出一個 n 個點,m 條邊的無向圖,需要求出圖中第 k 短的路徑

題目分析:k 是 400,本來以為是需要思考 k * n 或 k * m 的算法,搞了半天最后原來是 k^3 的算法。。

首先考慮,先把圖中前 k 小的邊全部拿出來,比較顯然的是,答案最壞也不可能超過第 k 小的這條邊

然后對于這 k 條邊涉及到的 2 * k 個點單獨拎出來跑弗洛伊德,然后將 k * ( k - 1 ) / 2 條路徑的權值排個序求第 k 小就是答案了

妙啊

2020.12.3UPDATE:

用bfs也可以做,昨天想到用bfs了,只不過不會對路徑判重,今天看題解受到啟發,可以將無向邊拆成兩條有向邊,然后求第 2 * k 小的路徑即是答案

興致勃勃寫了一發 n * k * logn 的算法,交上去 MLE 了,說明暴力擴展是不太合適的,所以考慮優化

可以將鄰接表中的所有鄰邊按照權值排序,并且對于每條邊來說,之前記錄的是 ( st , ed ),現在我們需要記錄一個中間點 x,也就是 ( st , x , ed ),滿足最后一條邊是 x -> ed,這樣還看不出來有什么好處,但是我們實際上記錄的是 ( st , x , index ),index 指的是 x 的鄰接表中的第 index 個元素,自然可以表示出 ed 了,并且還有一個最大的好處就是,在擴展的時候,將 st -> x -> index 這條邊撤回,改成 st -> x -> index+1 一定是最優的,所以擴展狀態的時候就有兩種途徑了:

  • ( st , x , index )擴展到(st , x , index + 1 )
  • ( st , x , index )擴展到(st , ed , 0),這里的 ed 就是 x 的第 index 個元素表示的點
  • 因為每次只擴展兩個狀態,所以 bfs 的復雜度是 O( n ) ,因為需要對每條邊排序,所以總時間復雜度是 O( nlogn ) 的

    代碼:
    Floyd:

    //#pragma GCC optimize(2) //#pragma GCC optimize("Ofast","inline","-ffast-math") //#pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> using namespace std;typedef long long LL;typedef unsigned long long ull;const LL inf=0x3f3f3f3f3f3f3f3f;const int N=1e3+100;struct Edge {int u,v,w;void input(){scanf("%d%d%d",&u,&v,&w);}bool operator<(const Edge& t)const{return w<t.w;} }edge[N*N];vector<int>node;LL maze[N][N];void floyd(int n) {for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)maze[i][j]=min(maze[i][j],maze[i][k]+maze[k][j]); }int get_id(int x) {return lower_bound(node.begin(),node.end(),x)-node.begin()+1; }void discreate() {sort(node.begin(),node.end());node.erase(unique(node.begin(),node.end()),node.end()); }int main() { #ifndef ONLINE_JUDGE // freopen("data.ans.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int n,m,k;scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=m;i++)edge[i].input();sort(edge+1,edge+1+m);for(int i=1;i<=k;i++){node.push_back(edge[i].u);node.push_back(edge[i].v);}discreate();n=node.size();for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)maze[i][j]=i==j?0:inf;for(int i=1;i<=k;i++){int u=get_id(edge[i].u),v=get_id(edge[i].v);maze[u][v]=maze[v][u]=edge[i].w;}floyd(n);vector<LL>ans;for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++)ans.push_back(maze[i][j]);nth_element(ans.begin(),ans.begin()+k-1,ans.end());printf("%lld\n",ans[k-1]);return 0; }

    bfs:

    //#pragma GCC optimize(2) //#pragma GCC optimize("Ofast","inline","-ffast-math") //#pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e6+100;struct Node {int st,ed,id;LL w;bool operator<(const Node& t)const{return w>t.w;} };set<pair<int,int>>vis;//st,edvector<pair<int,int>>node[N];priority_queue<Node>q;int main() { #ifndef ONLINE_JUDGE // freopen("data.ans.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int n,m,k;scanf("%d%d%d",&n,&m,&k);while(m--){int u,v,w;scanf("%d%d%d",&u,&v,&w);node[u].emplace_back(w,v);node[v].emplace_back(w,u);}for(int i=1;i<=n;i++){sort(node[i].begin(),node[i].end());q.push({i,i,0,node[i][0].first});vis.emplace(i,i);}k*=2;while(q.size()){auto cur=q.top();q.pop();if(cur.id+1<node[cur.ed].size())q.push({cur.st,cur.ed,cur.id+1,cur.w-node[cur.ed][cur.id].first+node[cur.ed][cur.id+1].first});if(vis.count(make_pair(cur.st,node[cur.ed][cur.id].second)))continue;vis.emplace(cur.st,node[cur.ed][cur.id].second);if(--k==0)return 0*printf("%lld\n",cur.w);q.push({cur.st,node[cur.ed][cur.id].second,0,cur.w+node[node[cur.ed][cur.id].second][0].first});}return 0; }

    ?

    總結

    以上是生活随笔為你收集整理的CodeForces - 1196F K-th Path(最短路+思维)好题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。