hdu 4619 Warm up 2(并查集活用)

周赛。

 1 /*
 2 比较简单的一题
 3 由于
 4 1、水平骨牌不能与水平骨牌相交,垂直骨牌也不能与垂直骨牌相交---即每边的端点最多只能与一边相连
 5 2、对于环,因为是正方形棋盘,没有斜边,所以环的边数一定是负数
 6 所以,基于这两点,可以用并查集找链与环,然后减去一半或一半减一的边即可
 7 */
 8 #include <cstdio>
 9 #include <cstring>
10 #define N 1005
11 #define M 105
12 
13 int a[M][M], ans[N*2];
14 int father[N*2];
15 int rank[N*2];
16 void Make_set(int x)
17 {
18     for(int i=1; i<=x; i++)
19     {
20         father[i] = i;
21         rank[i] = 0;
22     }
23 }
24 int find(int x)
25 {
26     if(x!=father[x])
27         father[x]=find(father[x]);
28     return father[x];
29 }
30 void Union(int x,int y)
31 {
32     x=find(x);
33     y=find(y);
34     if(x==y) return ;
35     if(rank[x]>rank[y])
36         father[y]=x;
37     else if(rank[x]<rank[y])
38         father[x]=y;
39     else {
40         rank[x]++;
41         father[y]=x;
42     }
43 }
44 
45 
46 int main()
47 {
48     int n, m, aa;
49     while(scanf("%d%d",&n,&m)!=EOF)
50     {
51         if(n==0 && m==0break;
52         Make_set(n+m);
53         memset(a, 0sizeof(a));
54         memset(ans, 0sizeof(ans));
55         aa=0;
56         int x, y;
57         for(int i=1; i<=n; i++)
58         {
59             scanf("%d%d",&x,&y);
60             a[y][x] = i;
61             a[y][x+1] = i;
62         }
63         for(int i=n+1; i<=n+m; i++)
64         {
65             scanf("%d%d",&x,&y);
66             if(a[y][x]>0)
67                 Union(a[y][x], i);
68             if(a[y+1][x]>0)
69                 Union(a[y+1][x], i);
70 
71         }
72         for(int i=1; i<=n+m; i++)
73         {
74             int t = find(i);
75             if(t!=i)
76                 ans[t]++;
77         }
78         for(int i=1; i<=n+m; i++)
79         {
80             if(ans[i]>0)
81             {
82                 ans[i]++;
83                 aa += ((ans[i])/2);
84             }
85         }
86         printf("%d ",m+n-aa);
87     }
88     return 0;
89 }

原文地址:https://www.cnblogs.com/byluoluo/p/3631380.html