P1967 货车运输
P1967 货车运输
思路:
将边权从大到小排序,然后建立最大生成树,在新图上求两个点的lca即可
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #include <cctype> 7 using namespace std; 8 9 #define inf 0x7f7f7f7f 10 #define LL long long 11 #define res register int 12 inline int read() 13 { 14 int x(0),f(1); char ch; 15 while(!isdigit(ch=getchar())) if(ch=='-') f=-1; 16 while(isdigit(ch)) x=x*10+ch-'0',ch=getchar(); 17 return f*x; 18 } 19 int n,m; 20 const int N=500000+5; 21 int head[N],nxt[N<<1],ver[N<<1],edge[N<<1],tot; 22 struct E{ 23 int u,v,w; 24 }e[N]; 25 int vis[N],fa[N],d[N]; 26 int f[N][22],dis[N][22]; 27 28 //inline int min(int a,int b){return a<b?a:b;} 29 inline bool cmp(E a,E b) {return a.w>b.w;} 30 inline void add(int x,int y,int z) { 31 ver[++tot]=y; nxt[tot]=head[x]; head[x]=tot; edge[tot]=z; 32 ver[++tot]=x; nxt[tot]=head[y]; head[y]=tot; edge[tot]=z; 33 } 34 //inline void swap(int &x,int &y) {int tmp=x; x=y; y=tmp;} 35 inline int get(int x) { 36 if(x==fa[x]) return x; return fa[x]=get(fa[x]); 37 } 38 39 inline void Kruskal() 40 { 41 sort(e+1,e+m+1,cmp); 42 for(res i=1 ; i<=n ; i++) fa[i]=i; 43 for(res i=1 ; i<=m ; i++) 44 { 45 int x=get(e[i].u),y=get(e[i].v),z=e[i].w; 46 if(x==y) continue; 47 fa[x]=y; 48 add(x,y,z); 49 } 50 } 51 52 void dfs(int x) 53 { 54 vis[x]=1; 55 for(res i(head[x]) ; i ; i=nxt[i]) 56 { 57 int y=ver[i]; 58 if(vis[y]) continue; 59 f[y][0]=x; dis[y][0]=edge[i]; 60 // printf("dis %d",dis[y][0]); 61 d[y]=d[x]+1; dfs(y); 62 } 63 } 64 65 inline int lca(int x,int y) 66 { 67 if(get(x)!=get(y)) return -1; 68 if(d[x]<d[y]) swap(x,y); 69 int ans=inf; 70 for(res i=20 ; i>=0 ; i--) 71 if(d[f[x][i]]>=d[y]) 72 { 73 ans=min(ans,dis[x][i]); 74 x=f[x][i]; 75 } 76 if(x==y) return ans; 77 for(res i=20 ; i>=0 ; i--) 78 if(f[x][i]!=f[y][i]) 79 { 80 ans=min(ans,dis[x][i]); 81 ans=min(ans,dis[y][i]); 82 x=f[x][i],y=f[y][i]; 83 } 84 ans=min(ans,dis[x][0]); 85 ans=min(ans,dis[y][0]); 86 return ans; 87 } 88 89 90 int main() 91 { 92 // freopen("in.txt","r",stdin); 93 n=read(); m=read(); 94 for(res i=1 ; i<=m ; i++) 95 e[i].u=read(), e[i].v=read(),e[i].w=read(); 96 Kruskal(); 97 for(res i=1 ; i<=n ; i++) 98 { 99 if(!vis[i]) 100 { 101 d[i]=1; dfs(i); 102 f[i][0]=i; dis[i][0]=inf; 103 } 104 } 105 //注意顺序 106 for(int i=1; i<=20; i++) 107 for(int j=1; j<=n; j++){ 108 f[j][i]=f[f[j][i-1]][i-1]; 109 dis[j][i]=min(dis[j][i-1], dis[f[j][i-1]][i-1]); 110 } 111 int q=read(); 112 for(res i=1 ; i<=q ; i++) 113 { 114 int x=read(),y=read(); 115 printf("%d\n",lca(x,y)); 116 } 117 return 0; 118 }