题意:给n个点和m条信息,每条信息表示x和y中有z个休息室,问能不能有一种符合条件且休息室个数最少的方案。
读入数据时,先判断z,若z等于2,则给x,y都染上色1,若x,y中有颜色0 则不行,若z等于0,则给x,y都染上色0,若x,y中有颜色1 则不行。若z=1,就在x,y间建一条边。
先以已经有颜色的点为起始点去dfs染色,染色过程中出现矛盾就不行
再对其他没有颜色的点dfs染色,如果有矛盾就不行,否则答案加上两种颜色个数中较小的
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5 + 10;
int n, m, col[N], h[N], cnt, vis[N], f, ans, sum, ct;
struct node {
int v, net;
} no[N << 2];
void add(int u, int v) {
no[cnt].v = v;
no[cnt].net = h[u];
h[u] = cnt++;
}
bool dfs1(int x, int co) {
vis[x] = 1;
col[x] = co;
if(co == 1)
ans++;
for(int i = h[x]; ~i; i = no[i].net) {
int v = no[i].v;
if(col[v] == col[x])
return false;
if(!vis[v] && col[v] == -1) {
if(!dfs1(v, co ^ 1))
return false;
}
}
return true;
}
bool dfs2(int x, int co) {
vis[x] = 1;
col[x] = co;
if(co == 1)
ct++;
sum++;
for(int i = h[x]; ~i; i = no[i].net) {
int v = no[i].v;
if(col[v] == col[x])
return false;
if(!vis[v] && col[v] == -1) {
if(!dfs2(v, co ^ 1))
return false;
}
}
return true;
}
int main() {
memset(col, -1, sizeof col);
memset(h, -1, sizeof h);
cin >> n >> m;
for(int u, v, w, i = 1; i <= m; i++) {
cin >> u >> v >> w;
if(w == 0) {
if(col[u] == 1 || col[v] == 1)
f = 1;
col[u] = col[v] = 0;
}
if(w == 2) {
if(col[u] == 0 || col[v] == 0)
f = 1;
col[u] = col[v] = 1;
}
if(w == 1) {
if((col[u] == 1 && col[v] == 1) || (col[u] == 0 && col[v] == 0))
f = 1;
add(u, v);
add(v, u);
}
}
for(int i = 1; i <= n; i++) {
if(!vis[i] && col[i] != -1) {
if(!dfs1(i, col[i]))
f = 1;
}
}
for(int i = 1; i <= n; i++) {
if(col[i] == -1) {
sum = 0, ct = 0;
if(!dfs2(i, 1))
f = 1;
ans += min(ct, sum - ct);
}
}
if(!f)
cout << ans;
else
cout << "impossible";
return 0;
}