【图论】洛谷P1330 封锁阳光大学 (黑白染色问题)

题目

LP1330

思路

本题思维难度比较大,实际写起代码来很容易(直接一遍过),所以注意这个分析过程。
首先,满足possible的条件大概是这样的:每条边的两端,有且只有一端有河蟹。
这样的话就考虑一个图的黑白染色过程,对于一个图,如果存在合理的黑白染色(即没有黑白相邻),就possible,否则impossible。对于possible的情况,黑色和白色中选一个较少的即可。
注意图论题要考虑给的图可能不连通的问题,所以应该每个连通块都做一次黑白染色,最后再汇总。

代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define _for(i,a,b) for(int i = a; i
#define _rep(i,a,b) for(int i = a; i<=b; i++)
using namespace std;

const int maxn = 10000+10;
const int maxm = 100000+10;
int n, m, cnt[2], ans, col[maxn];
vector<int> G[maxn];
bool vis[maxn], impossible;

bool dfs(int u, int c){
	if (vis[u]){
		if (col[u] != c) return false;
		return true;
	}
	vis[u] = true;
	col[u] = c;
	cnt[c]++;
	bool ok = true;
	_for(i,0,G[u].size()){
		if (!dfs(G[u][i], abs(c-1))) ok = false;
	}
	return ok;
}

void solve(int u){
	cnt[0] = cnt[1] = 0;
	if (!dfs(u, 1)) impossible = true;
	else {
		ans += min(cnt[0],cnt[1]);
	}
}

int main(){
	scanf("%d%d",&n,&m);
	_for(i,0,m){
		int u,v;
		scanf("%d%d",&u,&v);
		G[u].push_back(v);
		G[v].push_back(u);	
	}
	_rep(i,1,n)
		if(!vis[i] && !impossible)
			solve(i);
			
	if (impossible) printf("Impossible\n");
	else printf("%d\n", ans);
	
	return 0;
}

你可能感兴趣的:(9.noip及时复习,图论,染色)