分析
非常简单的染色问题
我们分两次BFS,一次选择把全部边变成红色,另一次显然
然后一个点显然变两次是一样的,所以我们当边的颜色是否与当前选择的颜色不同给连接的点染色,若已染则判断是否相同或不同
#include <iostream> #include <cstdio> #include <queue> #include <memory.h> using namespace std; const int N=1e5+10;; struct Edge { int u,v,nx,type; }g[2*N]; int cnt,list[N]; int n,m; bool b[N],vis[N]; int ok,ans=2147483647,lans[2]; void Add(int u,int v,char type) { g[++cnt]=(Edge){u,v,list[u],type=='R'?1:0};list[u]=cnt; g[++cnt]=(Edge){v,u,list[v],type=='R'?1:0};list[v]=cnt; } int BFS(int v0,int same) { queue<int> q; while (!q.empty()) q.pop(); q.push(v0);vis[v0]=1; lans[1]++; while (!q.empty()) { int u=q.front();q.pop(); for (int i=list[u];i;i=g[i].nx) { if (!vis[g[i].v]) { b[g[i].v]=g[i].type==same?b[u]:(b[u]^1); lans[b[u]^(g[i].type==same)]++; q.push(g[i].v); vis[g[i].v]=1; } else if (g[i].type==same&&b[u]!=b[g[i].v]||g[i].type!=same&&b[u]==b[g[i].v]) return -1; } } return min(lans[0],lans[1]); } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { int u,v;char c; scanf("%d%d",&u,&v); scanf("%c",&c); while (c!='R'&&c!='B') scanf("%c",&c); Add(u,v,c); } for (int i=0;i<2;i++) { bool p=1;int cans=0,nans=0; memset(b,0,sizeof b);memset(vis,0,sizeof vis); for (int j=1;j<=n;j++) if (!vis[j]) { lans[0]=lans[1]=0; cans=BFS(j,i); if (cans==-1) { p=0; break; } nans+=cans; } if (p) ans=min(ans,nans); ok+=p; } if (!ok) printf("-1"); else printf("%d",ans); }