I - Bond UVA - 11354Click
to open the link
The meaning of the question
: Given n points and m edges, each edge has a weight, now, given t queries, each query gives two values of a and b, and outputs the maximum edge weight between a and b. value,
There may be multiple paths from a to b, and it must be ensured that the maximum edge weight of the output is the smallest among all paths, that is,
Find a path that minimizes the maximum risk on the path.
Idea
: If we do it with a minimum spanning tree, we can guarantee that each edge must be the current minimum! But a little change is needed here, and an array needs to be added to record the distance from each point to the parent node, so this also means that we can't use path compression (except that the Find function is a little different, the rest is basically the same as the template )
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int par[50005],rk[50005],d[50005],dx[50005]; //d array records the distance to the parent node, par records the father node, rk records the depth int n,m; typedef struct edge { int x,y,cost; }edge; edge G[100005]; void init()//initialization { for(int i=1;i<=n;i++){ par [i] = i; rk[i]=0; d[i]=0; } } int Find(int x)//Attention! ! You can't use path compression here or you can't find the parent node! ! ! { if(x==by[x]) return x; return Find(par[x]); //Return to Find(par[x]) directly, do not return par[x]=Find(par[x]) } void unite(int x,int y,int c) { x=Find(x); y=Find(y); if(x==y) return ; if(rk[x]<rk[y]){ by[x]=y; d[x]=c;//Record the cost from the point to the parent node } else{ by[y]=x; d[y]=c; if(rk[x]==rk[y]) rk[x]++; } } bool cmp(edge a,edge b) { return a.cost<b.cost; } int query(int u,int v) { memset(dx,0,sizeof dx);//When dx records a certain point, the maximum value of the edge int ans1=1, ans2=0; //Set ans1=1 because the second while needs to exit the loop according to the value of dx, so it is necessary to ensure that the loop can also be pushed out when it finds itself while(1){ dx[u]=ans1; if(par[u]==u)//Push up to the root node break; ans1=max(ans1,d[u]); u = pair [u]; } while(1){ if(dx[v]){ //If u passes v when pushing up, return the maximum edge weight from u to v, that is, dx[v] ans2 = max (ans2, dx [v]); break; } else{ //Otherwise, v is pushed up, and the maximum edge weight is recorded at the same time, until dx[v] is not 0 ans2=max(ans2,d[v]); v=par[v]; } } return ans2; } intmain() { int case = 0; while(~scanf("%d%d",&n,&m)){ if(kase++) printf("\n"); init(); for(int i=0;i<m;i++) scanf("%d%d%d",&G[i].x,&G[i].y,&G[i].cost); sort(G,G+m,cmp); for(int i=0;i<m;i++){ unite(G[i].x,G[i].y,G[i].cost); } int t; scanf("%d",&t); int a,b; while(t--){ scanf("%d%d",&a,&b); printf("%d\n",query(a,b)); } } }