Gym

题目大意:n个点和m条限制(n,m<=4e5),每条限制可以规定两个点:

1)都是白色2)都是黑色3)一白一黑

问最多有多少个黑点,如果不能满足所有限制条件则输出impossible。

这是去年在训练赛上打过的一道题,因为比较经典所以决定fuxi一下。当时我很早就写出来了,然而wa了很多发最后才过的,坑点太多。

总体思路就是对于1,2类限制,直接给两点染上对应的颜色,对于3类限制,由于无法直接确定两点的颜色,因此给两点连边,有边直接相连的两点不能为同一颜色,这样就转化成了经典的二分图染色问题。

具体步骤大致如下:

1)构建限制,构建的过程中同时检查是否有矛盾(比如一个点已经被染成了白色,后来又来了一条边让它成为黑色,这样是不行的)。

2)对每一个已经染色的点,用dfs给它所在的整个连通块染色,染色的过程中检查是否有矛盾。(这一步将所有能确定颜色的点都确定下来了)。

3)剩下的不能确定颜色的点一定能够构成若干个连通块,对于每个连通块任选一点将其染成任意颜色,分别求出每个连通块黑色和白色的数量。

 1 #include<bits/stdc++.h>
 2 typedef long long ll;
 3 const int N=2e5+10,inf=0x3f3f3f3f;
 4 using namespace std;
 5 int hd[N],ne,n,m,col[N],flag,black,white;
 6 struct E {int v,nxt;} e[N<<1];
 7 void link(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
 8 int dfs(int u,int c) {
 9     if(~col[u])return col[u]==c;
10     col[u]=c;
11     c==1?++black:++white;
12     for(int i=hd[u]; ~i; i=e[i].nxt) {
13         int v=e[i].v;
14         if(!dfs(v,c^1))return 0;
15     }
16     return 1;
17 }
18 int solve() {
19     for(int u=1; u<=n; ++u)if(~col[u])
20             for(int i=hd[u]; ~i; i=e[i].nxt) {
21                 int v=e[i].v;
22                 if(!dfs(v,col[u]^1))return -1;
23             }
24     int ret=0;
25     for(int i=1; i<=n; ++i)if(col[i]==1)++ret;
26     for(int i=1; i<=n; ++i)if(!~col[i]) {
27             black=white=0;
28             if(!dfs(i,0))return -1;
29             ret+=min(black,white);
30         }
31     return ret;
32 }
33 int main() {
34     scanf("%d%d",&n,&m);
35     memset(hd,-1,sizeof hd),ne=0;
36     memset(col,-1,sizeof col);
37     flag=1;
38     while(m--) {
39         int u,v,c;
40         scanf("%d%d%d",&u,&v,&c);
41         if(c==0) {
42             if(col[u]==1||col[v]==1)flag=0;
43             col[u]=col[v]=0;
44         } else if(c==2) {
45             if(col[u]==0||col[v]==0)flag=0;
46             col[u]=col[v]=1;
47         } else link(u,v),link(v,u);
48     }
49     if(!flag)puts("impossible");
50     else {
51         int ans=solve();
52         if(~ans)printf("%d
",ans);
53         else puts("impossible");
54     }
55     return 0;
56 }
原文地址:https://www.cnblogs.com/asdfsag/p/12426750.html