bzoj3732: Network(最小生成樹+LCA)
阿新 • • 發佈:2018-03-23
name cmp names tar sans scan bzoj3732 區間 ret
3732: Network
題目:傳送門
題解:
第一眼就看到最大邊最小,直接一波最小生成樹。
一開始還擔心會錯,問了一波肉大佬,任意兩點在最小生成樹上的路徑最大邊一定是最小的。
那麽事情就變得簡單起來了嘿嘿嘿,建棵樹,直接在線LCA啊,用一個mx[i][j]記錄i往上2^j這段區間的最大值。
代碼:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5#include<algorithm> 6 using namespace std; 7 struct node 8 { 9 int x,y,c; 10 }a[111000];int len; 11 void ins(int x,int y,int c) 12 { 13 len++;a[len].x=x;a[len].y=y;a[len].c=c; 14 } 15 struct edge 16 { 17 int x,y,c,next; 18 }e[111000];int llen,last[15100]; 19 void inss(intx,int y,int c) 20 { 21 llen++;e[llen].x=x;e[llen].y=y;e[llen].c=c; 22 e[llen].next=last[x];last[x]=llen; 23 } 24 int fa[15100]; 25 int findfa(int x){if(fa[x]!=x)fa[x]=findfa(fa[x]);return fa[x];} 26 bool cmp(node n1,node n2){return n1.c<n2.c;} 27 int n,m,T; 28 int bin[21],dep[15100],f[15100][21]; 29 int mx[15100][21];//記錄i~i+2^j的最大邊值 30 void pre_tree_node(int x) 31 { 32 for(int i=1;i<=20 && dep[x]>=bin[i];i++) 33 f[x][i]=f[f[x][i-1]][i-1],mx[x][i]=max(mx[x][i-1],mx[f[x][i-1]][i-1]); 34 for(int k=last[x];k;k=e[k].next) 35 { 36 int y=e[k].y; 37 if(y!=f[x][0]) 38 { 39 dep[y]=dep[x]+1; 40 f[y][0]=x;mx[y][0]=e[k].c; 41 pre_tree_node(y); 42 } 43 } 44 } 45 int sol(int x,int y) 46 { 47 int maxx=0; 48 if(dep[x]<dep[y])swap(x,y); 49 for(int i=20;i>=0;i--) 50 if(dep[x]-dep[y]>=bin[i]) 51 maxx=max(maxx,mx[x][i]),x=f[x][i]; 52 if(x==y)return maxx; 53 for(int i=20;i>=0;i--) 54 if(dep[x]>=bin[i] && f[x][i]!=f[y][i]) 55 maxx=max(maxx,max(mx[x][i],mx[y][i])),x=f[x][i],y=f[y][i]; 56 maxx=max(maxx,max(mx[x][0],mx[y][0])); 57 return maxx; 58 } 59 int main() 60 { 61 bin[0]=1;for(int i=1;i<=20;i++)bin[i]=bin[i-1]<<1; 62 scanf("%d%d%d",&n,&m,&T); 63 llen=len=0;memset(last,0,sizeof(last)); 64 for(int i=1;i<=m;i++) 65 { 66 int x,y,c;scanf("%d%d%d",&x,&y,&c); 67 ins(x,y,c);ins(y,x,c); 68 } 69 sort(a+1,a+len+1,cmp); 70 for(int i=1;i<=n;i++)fa[i]=i;int tt=0; 71 for(int i=1;i<=len;i++) 72 { 73 int fx=findfa(a[i].x),fy=findfa(a[i].y); 74 if(fx!=fy) 75 { 76 fa[fy]=fx,tt++; 77 inss(a[i].x,a[i].y,a[i].c); 78 inss(a[i].y,a[i].x,a[i].c); 79 if(tt==n-1)break; 80 } 81 } 82 for(int i=1;i<=n;i++) 83 if(fa[i]==i) 84 f[i][0]=0,dep[i]=1,pre_tree_node(i); 85 while(T--) 86 { 87 int st,ed;scanf("%d%d",&st,&ed); 88 printf("%d\n",sol(st,ed)); 89 } 90 return 0; 91 }
bzoj3732: Network(最小生成樹+LCA)