题目传送门
题意是给你一张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;
}