和NOIP2013货车运输几乎一样
然后又双叒叕wa了
原因:
思路吗肥肠简单,对于原图进行最小生成树,这里用克鲁斯卡尔
可以发现所选路径一定是这两个点在生成树上的简单路径
证明:
如果有一条更小,它就会被选进最小生成树,这不符合最小生成树的定义,故失败
然后LCA和倍增即可
代码:
#include<bits/stdc++.h> using namespace std; const int N=300005; int n,m,Q; struct node{ int from,to,val; }s[N*2]; int hed[N*2],nxt[N*2],cnt=0; int n_hed[N*2],n_nxt[N*2],n_val[N*2],n_tal[N*2]; int n_cnt=0; int f[N]; int jump[N][25]={0}; int value[N][25]={0}; bool vis[N]={0}; int dep[N]; inline int find(int x){ if(f[x]!=x) f[x]=find(f[x]); return f[x]; } inline void unionn(int x,int y){ int fa=find(x); int fb=find(y); if(fa!=fb) f[fa]=fb; } inline void addege(int x,int y,int z){ cnt++; s[cnt].to=y; s[cnt].val=z; s[cnt].from=x; nxt[cnt]=hed[x]; hed[x]=cnt; } inline void n_addege(int x,int y,int z){ n_cnt++; n_tal[n_cnt]=y; n_val[n_cnt]=z; n_nxt[n_cnt]=n_hed[x]; n_hed[x]=n_cnt; } inline bool cmp(node x,node y){ return x.val<y.val; } inline void dfs(int u,int fa){ vis[u]=1; for(int i=n_hed[u];i;i=n_nxt[i]){ int v=n_tal[i]; if(v==fa) continue; dep[v]=dep[u]+1; dfs(v,u); jump[v][0]=u; value[v][0]=n_val[i]; } } inline int lca(int x,int y){ int ans=0; if(dep[x]>dep[y]) swap(x,y); for(int i=20;i>=0;i--){ if(dep[jump[y][i]]>=dep[x]){ ans=max(ans,value[y][i]); y=jump[y][i]; } } if(x==y) return ans; for(int i=20;i>=0;i--){ if(jump[x][i]!=jump[y][i]){ ans=max(ans,value[x][i]); ans=max(ans,value[y][i]); x=jump[x][i]; y=jump[y][i]; } } ans=max(ans,value[x][0]); ans=max(ans,value[y][0]); return ans; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z); addege(x,y,z); } for(int i=1;i<=n;i++) f[i]=i; sort(s+1,s+cnt+1,cmp); for(int i=1;i<=cnt;i++){ if(find(s[i].from)!=find(s[i].to)){ unionn(s[i].from,s[i].to); n_addege(s[i].from,s[i].to,s[i].val); n_addege(s[i].to,s[i].from,s[i].val); } } //root有多个 for(int i=1;i<=n;i++){ if(vis[i]==0){ dep[i]=1; dfs(i,-1); jump[i][0]=i; value[i][0]=0; } } for(int i=1;i<=20;i++){ for(int j=1;j<=n;j++){ jump[j][i]=jump[jump[j][i-1]][i-1]; value[j][i]=max(value[j][i-1],value[jump[j][i-1]][i-1]); } } scanf("%d",&Q); while(Q--){ int x,y; scanf("%d%d",&x,&y); if(find(x)!=find(y)){ printf("impossible\n"); continue; } printf("%d\n",lca(x,y)); } return 0; }
原文:https://www.cnblogs.com/QYJ060604/p/11616317.html