codeforces#1196F. K-th Path(最短路,思维题)

题目链接:

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;
}

  

原文地址:https://www.cnblogs.com/carcar/p/11182194.html