洛谷P1653 猴子
1 #include<bits/stdc++.h> 2 using namespace std; 3 inline void read(int &tmp) 4 { 5 int x=1;char c=getchar(); 6 for(tmp=0;!isdigit(c);c=getchar()) if(c=='-') x=-1; 7 for(;isdigit(c);tmp=tmp*10+c-48,c=getchar()); 8 tmp*=x; 9 } 10 const int maxn=2000005; 11 const int maxm=4000005; 12 const int INF=0x3f3f3f3f; 13 struct node{//并查集 14 int val,fa;//val- 权值(时间) 15 }f[maxn]; 16 struct data{//链表 17 int l,r; 18 }my_list[maxn]; 19 struct edge{//存边 20 int f,s;//f-编号 s-左右手 21 }e[maxn]; 22 bool del[maxn][5];//标记已删除的边 23 int find(int x) 24 { 25 if(f[x].fa==x) return x; 26 int root=find(f[x].fa); 27 f[x].val=min(f[x].val,f[f[x].fa].val);//不断更新最小值 28 return f[x].fa=root; 29 } 30 void Union(int x,int y,int z)//用并查集在x和y之间连一条权值为z的边 31 { 32 x=find(x),y=find(y); 33 if(x==y) return; 34 if(x==1) f[y].fa=x,f[y].val=z;//默认1号为根节点 35 else f[x].fa=y,f[x].val=z; 36 } 37 int n,m; 38 int main() 39 { 40 read(n),read(m); 41 for(int i=1;i<=n;i++) f[i].fa=i,f[i].val=INF;//初始化 42 for(int i=1;i<=n;i++) read(my_list[i].l),read(my_list[i].r); 43 for(int i=1;i<=m;i++) 44 { 45 read(e[i].f);read(e[i].s);//读入边 46 del[e[i].f][e[i].s]=true;//标记已删除 47 } 48 for(int i=1;i<=n;i++)//将最后连在一起的猴子并在一起 49 { 50 if(!del[i][1]&&my_list[i].l!=-1) Union(i,my_list[i].l,INF); 51 if(!del[i][2]&&my_list[i].r!=-1) Union(i,my_list[i].r,INF); 52 } 53 for(int i=m;i>=1;i--)//倒序处理 54 { 55 if(e[i].s==1&&my_list[e[i].f].l!=-1) Union(e[i].f,my_list[e[i].f].l,i-1); 56 if(e[i].s==2&&my_list[e[i].f].r!=-1) Union(e[i].f,my_list[e[i].f].r,i-1); 57 } 58 for(int i=1;i<=n;i++) 59 { 60 find(i);//路径压缩 更新权值 61 printf("%d\n",f[i].val==INF?-1:f[i].val); 62 } 63 return 0; 64 }