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\n",ans);
return 0;
}