题目链接:
https://codeforces.com/contest/1196/problem/F
题意:
在无向图的所有最短路点对中,求出第$k$大
数据范围:
$ 1 leq k leq 400$
分析:
其实只需要保留$k$条边,这样已经有了$k$个点对的距离小于排好序后第$k$条边的距离
再调用弗洛伊德算法$O(k^3)$
ac代码:
#include<bits/stdc++.h> #define ll long long #define PI acos(-1.0) #define pa pair<int,char> using namespace std; const int maxn=200+10; const int maxm=5e4+10; const ll mod=1e9+7; struct Edge { int a,b,g,s; bool operator<(Edge & z)const { if(z.g==g)return s<z.s; return g<z.g; } }edge[maxm]; Edge now[maxn]; ll G,S,ans=2e18; int boss[maxn],top,n,m; int fin(int x) { if(boss[x]==x)return x; return boss[x]=fin(boss[x]); } void uni(int a,int b) { boss[fin(a)]=fin(b); } int main() { scanf("%d %d",&n,&m); scanf("%lld %lld",&G,&S); for(int i=1;i<=m;i++) scanf("%d %d %d %d",&edge[i].a,&edge[i].b,&edge[i].g,&edge[i].s); sort(edge+1,edge+1+m); for(int i=1;i<=m;i++) { int cnt=0; now[++top]=edge[i]; for(int j=top;j>=2;j--)if(now[j].s<now[j-1].s)swap(now[j],now[j-1]); for(int j=1;j<=n;j++)boss[j]=j; for(int j=1;j<=top;j++) { Edge zz=now[j]; if(fin(zz.a)==fin(zz.b))continue; now[++cnt]=zz; uni(zz.a,zz.b); } top=cnt; if(cnt==n-1)ans=min(ans,edge[i].g*G+now[top].s*S); //cout<<edge[i].g<<" "<<now[top].s<<endl; } if(ans==2e18)printf("-1 "); else printf("%lld ",ans); return 0; }