jzoj4672-Graph Coloring【图论,模拟】

版权声明:原创,未经作者允许禁止转载 https://blog.csdn.net/Mr_wuyongcong/article/details/88758992

正题


题目大意

一张无向图,每条边有一个颜色(红或蓝),可以选择点使得连接的边都取反,求至少要选多个点可以使得所有边的颜色相同。


解题思路

不难发现如果确定所有边的颜色,然后知道一个点的选择后就可以知道整个联通图的选择。因为如果一个点的选择被确定了,他连接的点的选择也可以被确定。


c o d e code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=110000,inf=2147483647/3;
struct edge{
	int to,next,w;
}a[N*2];
int ls[N],tot,mins,sum,n,m;
bool v[N],f[N],flag,run[N];
void addl(int x,int y,char w)
{
	a[++tot].to=y;
	a[tot].next=ls[x];
	ls[x]=tot;
	a[tot].w=(w=='R');
}
void dfs(int x)
{
	v[x]=run[x]=1;
	for(int i=ls[x];i;i=a[i].next)
	{
		if(flag) break;
		int y=a[i].to;
		if(!v[y]){
			f[y]=f[x]^a[i].w;
			if(f[y]) sum++;
			dfs(y);
		}
		else if(f[y]!=f[x]^a[i].w)
			flag=1;
	}
}
void get_ans()
{
	memset(run,0,sizeof(run));
	int ans=0,k;
	for(int i=1;i<=n;i++)
	  if(!run[i]){
	  	f[i]=sum=flag=0;
	  	memset(v,0,sizeof(v));
	  	dfs(i);
	  	if(flag) k=inf;
	  	else k=sum;
	  	f[i]=sum=1;flag=0;
	  	memset(v,0,sizeof(v));
	  	dfs(i);
	  	if(flag) sum=inf;
	  	if(k==inf&&sum==inf){
	  		ans=inf;
	  		break;
	  	}
	  	ans+=min(k,sum);
	  }
	mins=min(ans,mins);
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int x,y;char c;
		scanf("%d %d %c",&x,&y,&c);
		addl(x,y,c);
		addl(y,x,c);
	}
	mins=inf;
	get_ans();
	for(int i=1;i<=tot;i++)
	  a[i].w^=1;
	get_ans();
	if(mins==inf) printf("-1");
	else printf("%d",mins);
}

猜你喜欢

转载自blog.csdn.net/Mr_wuyongcong/article/details/88758992