jzoj 4672. 【NOIP2016提高A组模拟7.20】Graph Coloring

Description

现在你有一张无向图包含n个节点m条边。最初,每一条边都是蓝色或者红色。每一次你可以将一个节点连接的所有边变色(从红变蓝,蓝变红)。
找到一种步数最小的方案,使得所有边的颜色相同。

Input

第一行包含两个数n,m(1<=n,m<=100000)分别代表节点数和边的数量
接下来m行描述边,第i行ui,vi,ci,代表ui有一条颜色为ci的边与vi相连(ci是B或者是R),B代表蓝色,R代表红色。数据保证没有自环的边。

Output

如果没有方案就输出-1。否则第一行输出k代表最小的步数

Sample Input

输入1:
3 3
1 2 B
3 1 R
3 2 B

输入3:
4 5
1 2 R
1 3 R
2 3 B
3 4 B
1 4 B

Sample Output

输出1:
1

输出3:
-1

Data Constraint

对于30%数据,n<=20,m<=20

Solution

这题我们通过样例1可以发现:we need to 分类讨论
因为如果单纯考虑全染成B的情况的话,答案就错了。
于是分类讨论ing。。。
由于图不一定完全联通,所以我们要枚举每个点
然后,对于每一块,我们分类讨论,每个都得到了一个染色数目a,我们就将s+min(a,这一块的大小-a)。
(PS:如果我们发现无法染成相同的话,就break掉即可)

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100010
using namespace std;
struct node{int v,fr,color;}e[N<<1];
int n,m,c[N],tail[N],color,cnt=0,s,s1,s2,ans=100001;
char ch;

inline int read()
{
	int x=0; char c=getchar();
	while (c<'0' || c>'9') c=getchar();
	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x;
}

inline void add(int u,int v,int check) {e[++cnt]=(node){v,tail[u],check}; tail[u]=cnt;}

void dfs(int x)
{
	if (c[x]) s1++; else s2++;
	for (int p=tail[x],v,col;p;p=e[p].fr)
	{
		v=e[p].v,col=(c[x]+e[p].color+color) & 1;
		if (c[v]==-1) c[v]=col,dfs(v);
		else if (c[v]!=col) s=-1;
		if (s==-1) return;
	}
}

int main()
{
//	freopen("Graph Coloring.in","r",stdin);
//	freopen("Graph Coloring.out","w",stdout);
	n=read(),m=read();
	for (int i=1,u,v;i<=m;i++)
	{
		u=read(),v=read(),ch=getchar();
		add(u,v,ch=='R'),add(v,u,ch=='R');
	}
	for (color=0;color<=1;color++)
	{
		s=0;
		memset(c,-1,sizeof(c));
		for (int i=1;i<=n;i++)
			if (c[i]==-1)
			{
				c[i]=1,s1=s2=0,dfs(i);
				if (s==-1) break;
				s+=std::min(s1,s2);
			}
		if (s!=-1) ans=std::min(s,ans);
	}
	if (ans==100001) puts("-1");
	else printf("%d
",ans);
	return 0;
}
转载需注明出处。
原文地址:https://www.cnblogs.com/jz929/p/11817544.html