题解:luogu.P1330 封锁阳光大学(图论配套精选专练)

题目:P1330 封锁阳光大学

题意建模

有给定一张图,N 个点,M 条边,能否将整张图二分。

算法分析

现在要求对若干条边进行染色即能否将整张图二分。这是二分图的常见处理方法。怎样染色?定义状态 f(s,color) ,表示在当前状态下,是哪一个节点(s);又是哪一种颜色(color)。那么现在就很明显,对整张图进行遍历,这里可以选用深度优先(DFS),也可以选用广度优先(BFS)。我们给出前者的 CODE 如下:

参考程序

//luogu.P1330.DFS实现
#include
#include
#include
#include
using namespace std;
const int N=1e4+5,M=1e5+5;
vector  e[M];//vector存边
int mark[M];
int n,m,ans,cnt,c[N];//c[]记录所有节点的颜色

void dfs(int node,int col)//定义状态,当前节点编号及其颜色
{
	if(c[node]!=-1 && c[node]!=col) {cout<<"Impossible"<>n>>m;
	for(int i=1;i<=m;i++) 
	{
		int u,v;
		cin>>u>>v;
		e[u].push_back(v); 
		e[v].push_back(u);
	}
	memset(mark,0,sizeof(mark));
	for(int i=1;i<=n;i++) 
	if(!mark[i])
	{
		memset(c,-1,sizeof(c));//初始化c[]为-1,后续只有两种颜色:0-1
		cnt=0;
		dfs(i,0);
		int sum=0;
		for(int i=1;i<=n;i++) sum+=c[i]==1;//初始是0,染一次变成1,所以这一类染的次数等于(1)河蟹的个数 
		ans+=min(sum,cnt-sum);//将染成1的数量与染成0的数量取min并加在ans上 
	}
	cout<

细节研讨

  • 注意染色的顺序和意义
  • 每次进入下一个节点时都要异或1,表示不同的联通块

你可能感兴趣的:(图论)