洛谷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
",f[i].val==INF?-1:f[i].val);
62     } 
63     return 0;
64 }
原文地址:https://www.cnblogs.com/yu-xing/p/10261429.html