版权声明:原创,未经作者允许禁止转载 https://blog.csdn.net/Mr_wuyongcong/article/details/88758992
正题
题目大意
一张无向图,每条边有一个颜色(红或蓝),可以选择点使得连接的边都取反,求至少要选多个点可以使得所有边的颜色相同。
解题思路
不难发现如果确定所有边的颜色,然后知道一个点的选择后就可以知道整个联通图的选择。因为如果一个点的选择被确定了,他连接的点的选择也可以被确定。
#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);
}