正题
题目大意
一张无向图,每条边有一个颜色(红或蓝),可以选择点使得连接的边都取反,求至少要选多个点可以使得所有边的颜色相同。
解题思路
不难发现如果确定所有边的颜色,然后知道一个点的选择后就可以知道整个联通图的选择。因为如果一个点的选择被确定了,他连接的点的选择也可以被确定。
codecodecode
#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);
}