洛谷 P1330 封锁阳光大学

题目传送门

解题思路:

我们将整个图的所有点分别染成两种颜色,例如绿色和黄色,我们每选一个点,就将它染成绿色,并将所有与它相连的点染成黄色.

在染色过程中,如果发现相邻的两个点是同一种颜色,则说明impossible.

如果成功染完全图,就看选绿色更优还是黄色更优.

AC代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 
 4 using namespace std;
 5 
 6 int n,m,fa[10001],v[10001],a,b,h[10001]; 
 7 bool bj[10001];
 8 long long ans;
 9 
10 inline int find_father(int x) {
11     if(fa[x] == x) return fa[x];
12     else return fa[x] = find_father(fa[x]);
13 }
14 
15 inline void merge(int x,int y) {
16     int x1 = find_father(x);
17     if(x1 != y) {
18         fa[y] = x1;
19         v[x1] += v[y];
20     }
21 }
22 
23 int main()
24 {
25     scanf("%d%d",&n,&m);
26     for(int i = 1;i <= n; i++) {
27         fa[i] = i;
28         v[i] = 1;
29     }
30     for(int i = 1;i <= m; i++) {
31         scanf("%d%d",&a,&b);
32         int f1 = find_father(a);
33         int f2 = find_father(b);
34         if(f1 != f2) {
35             if(h[a]) merge(h[a],f2);
36             if(h[b]) merge(h[b],f1);
37             h[a] = f2;
38             h[b] = f1;
39         }
40         else {
41             printf("Impossible");
42             return 0;
43         }
44     }
45     for(int i = 1;i <= n; i++) {
46         int q = find_father(i);
47         if(!bj[q]) {
48             int u = find_father(h[i]);
49             ans += min(v[u],v[q]);
50             bj[u] = 1;
51             bj[q] = 1;
52         }
53     }
54     printf("%lld",ans);
55     return 0;
56 }

 

posted @ 2019-08-04 22:40  Mr^Simon  阅读(140)  评论(0编辑  收藏  举报