P1396 营救(最小生成树+最短路记录路径)

题目传送门

题意是给你一张n个点的无向图,给m条边,可能有重边,要从s走到t,要求途中经过的道路的权值的最大值最小,求出这个答案。

思路:
因为尽量要小的权值,那很容易想到最小生成树。我们先用kruskal建立最小生成树之后,就得到了一张边权和最小的图,然后Dijkstra跑一遍,记录路径和权值,最后路径回溯维护最大值。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
const int inf=0x7fffffff;
const int mod=1e9+7;
const int eps=1e-6;
typedef long long ll;
typedef unsigned long long ull;
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl '\n'
int head[N<<1],nxt[N<<1],to[N<<1],val[N<<1],tot=0,crt=0;
struct node
{
    int x,y,z;
}e[N<<1];
void addedge(int u,int v,int w,int p)
{
    if(p==1)
    {
        e[++tot].x=u;
        e[tot].y=v;
        e[tot].z=w;
    }
    if(p==2)
    {
        nxt[++crt]=head[u];
        to[crt]=v;
        val[crt]=w;
        head[u]=crt;
    }
}
int dis[N],vis[N],pre[N];int n;
void dijkstra(int s)
{
    for(int i=1;i<=n;i++)
        dis[i]=inf,vis[i]=0;
    priority_queue<pii>q;
    dis[s]=0;
    q.push(mp(-dis[s],s));
    while(!q.empty())
    {
        int u=q.top().second;
        int d=q.top().first;
        q.pop();
        if(!vis[u])
        {
            vis[u]=1;
            for(int i=head[u];i;i=nxt[i])
            {
                int v=to[i];
                if(dis[v]>dis[u]+val[i])
                {
                    dis[v]=dis[u]+val[i];
                    pre[v]=u;
                    q.push(mp(-dis[v],v));
                }
            }
        }
    }
}
int fa[N];
int finds(int x)
{
    if(fa[x]==x)
        return x;
    return fa[x]=finds(fa[x]);
}
bool cmp(node a,node b)
{
    return a.z<b.z;
}
signed main()
{
    IOS;
    int m,s,t;
    cin>>n>>m>>s>>t;
    for(int i=1;i<=m;i++)
    {
        int u,v,w;
        cin>>u>>v>>w;
        addedge(u,v,w,1);
        addedge(v,u,w,1);
    }
    for(int i=1;i<=n;i++)
        fa[i]=i;
    sort(e+1,e+tot+1,cmp);
    int cnt=n;
    for(int i=1;i<=tot;i++)
    {
        if(cnt==1)
            break;
        int xx=finds(e[i].x),yy=finds(e[i].y);
        if(xx!=yy)
        {
            fa[xx]=yy;
            addedge(e[i].x,e[i].y,e[i].z,2);
            addedge(e[i].y,e[i].x,e[i].z,2);
            cnt--;
        }
    }
    dijkstra(s);
    int now=t;
    int res=-1;
    while(now!=s)
    {
        res=max(res,dis[now]-dis[pre[now]]);
        now=pre[now];
    }
    cout<<res<<endl;
}

发布了93 篇原创文章 · 获赞 9 · 访问量 4203

猜你喜欢

转载自blog.csdn.net/Joker_He/article/details/105196060