一、题目
二、解法
刚开始一看可能没有什么思路,但是这个问题很像染色,先枚举最终染上的颜色,如果确定了一个点是否能够翻转,那么与其相连的点也能确定。
所以考虑对于每一个连通块,把他的第一个点设置成翻转,就可能拿到翻转点和不翻转点的个数,如果把第一个点设置成不翻转,那么所有点的翻转状态都会反过来,所以贪心地把这两者取 即可。
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
using namespace std;
#define inf 1e9
const int M = 100005;
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,m,fl,col,ans=inf,tot,t0,t1,f[M],vis[M];char s[5];
struct edge
{
int v,c,next;
}e[2*M];
vector<int> v,v0,v1,v3;
void dfs(int u,int c)
{
vis[u]=c;
if(c==0) t0++,v0.push_back(u);
else t1++,v1.push_back(u);
for(int i=f[u];i;i=e[i].next)
{
int v=e[i].v,w=e[i].c;
if(vis[v]==-1)
dfs(v,c^w^col);
else if(vis[u]^vis[v]^w!=col)
{
fl=1;
return ;
}
}
}
signed main()
{
n=read();m=read();
for(int i=1;i<=m;i++)
{
int u=read(),v=read();scanf("%s",s);
e[++tot]=edge{v,s[0]=='R',f[u]},f[u]=tot;
e[++tot]=edge{u,s[0]=='R',f[v]},f[v]=tot;
}
for(col=0;col<=1;col++)
{
int tmp=0;fl=0;
v3.clear();
memset(vis,-1,sizeof vis);
for(int i=1;i<=n;i++)
if(vis[i]==-1)
{
v0.clear();v1.clear();
t0=t1=0;
dfs(i,1);
if(fl) break;
tmp+=min(t0,t1);
if(t0<t1)
{
for(int i=0;i<v0.size();i++)
v3.push_back(v0[i]);
}
else
{
for(int i=0;i<v1.size();i++)
v3.push_back(v1[i]);
}
}
if(fl) continue;
if(ans>tmp)
{
ans=tmp;
v=v3;
}
}
if(ans==inf) puts("-1");
else
{
printf("%d\n",ans);
for(int i=0;i<v.size();i++)
printf("%d ",v[i]);
puts("");
}
}