Codeforces Gym100502A:Amanda Lounges(DFS染色)

http://codeforces.com/gym/100502/attachments

题意:有n个地点,m条边,每条边有一个边权,0代表两个顶点都染成白色,2代表两个顶点都染成黑色,1代表两个顶点可能尚未染色,但是之后必须一个染成白色一个染成黑色。问是否有可能让这个图成功染色,如果可能输出染成黑色的最少顶点数。

思路:一开始0和2的边是确定的,直接染,如果有矛盾直接false。然后利用边权为1的边建图。先考虑如果图中的某个点已经染色了,那么直接DFS染色,然后这个阶段出现黑色的点是确定的(因为必须染成这个颜色),如果出现矛盾就返回。

再考虑如果图中没有点染色,这个时候随便染一种颜色,用两个计数器a和b,代表这个阶段染成白色的点和黑色的点的数目,这个对答案的贡献为min(a, b),因为点都是不确定的,所以染成白和染成黑都是一样的,所以可以互换,然后出现矛盾就返回。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define N 200010
 4 struct Edge {
 5     int v, nxt;
 6 } edge[N*2];
 7 int vis[N], head[N], tot, col[N], a, b, ans;
 8 
 9 void Add(int u, int v) {
10     edge[tot] = (Edge) {v, head[u]}; head[u] = tot++;
11     edge[tot] = (Edge) {u, head[v]}; head[v] = tot++;
12 }
13 
14 bool DFS(int u, int c, int kind) {
15     if(kind) {
16         if(col[u] == 1) b++; else a++;
17     } else {
18         if(col[u] == 1) ans++;
19     }
20     for(int i = head[u]; ~i; i = edge[i].nxt) {
21         int v = edge[i].v;
22         if(col[v] == c) return false;
23         if(!vis[v]) { vis[v] = 1; if(col[v] == 0) col[v] = -c; if(!DFS(v, col[v], kind)) return false; }
24     }
25     return true;
26 }
27 
28 int main() {
29     int n, m;
30     scanf("%d%d", &n, &m);
31     memset(head, -1, sizeof(head));
32     bool flag = 1;
33     for(int i = 0; i < m; i++) {
34         int u, v, k;
35         scanf("%d%d%d", &u, &v, &k);
36         if(k == 2) {
37             if(col[u] == -1 || col[v] == -1) flag = 0;
38             col[u] = col[v] = 1;
39         } else if(k == 0) {
40             if(col[u] == 1 || col[v] == 1) flag = 0;
41             col[u] = col[v] = -1;
42         } else Add(u, v);
43     }
44     for(int i = 1; i <= n; i++)
45         if(!vis[i] && col[i]) { vis[i] = 1;  if(!DFS(i, col[i], 0)) flag = 0; }
46     for(int i = 1; i <= n; i++) {
47         if(vis[i]) continue;
48         a = 0; b = 0; vis[i] = 1; col[i] = 1;
49         if(!DFS(i, 1, 1)) flag = 0;
50         ans += a > b ? b : a;
51     }
52     if(!flag) puts("impossible");
53     else printf("%d
", ans);
54     return 0;
55 }
原文地址:https://www.cnblogs.com/fightfordream/p/6519248.html