Codeforces Round #747 (Div. 2) D. The Number of Imposters (二分图染色)
-
题意:有一张\(n\)个点的有向图,\(u-(I/C)>v\),表示\(u\)说\(v\)是\(I/C\),假如\(u\)是\(C\)那么他说的是真话,否则是假话,现在要你给所有点赋值\(I/C\),问你怎么赋值才能保证合法且\(I\)的数量最大。
-
题解:\(u-(I)>v\),假如\(u\)是\(I\),那么\(v\)是\(I\),假如\(u\)是\(C\),那么\(v\)是\(C\),\(u-(C)>v\),假如\(u\)是\(I\),那么\(v\)是\(C\),假如\(u\)是\(C\),那么\(v\)是\(I\),所以我们发现,边权为\(I\)的两点必然相同,\(C\)的两点必然不同,那么连通块内的某一个点赋值后,其他点的值也就确定了,因为只有两种赋值情况,所以可以用二分图染色来写,并且注意到初始点的赋值不同,两种结果是相反的,所以我们染完色后只需取最大即可,而不用再跑一次。
-
代码:
#include <bits/stdc++.h> #define ll long long #define fi first #define se second #define pb push_back #define me memset #define rep(a,b,c) for(int a=b;a<=c;++a) #define per(a,b,c) for(int a=b;a>=c;--a) const int N = 1e6 + 10; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; using namespace std; typedef pair<int,int> PII; typedef pair<ll,ll> PLL; ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;} ll lcm(ll a,ll b) {return a/gcd(a,b)*b;} int n,m; vector<PII> edge[N]; char s[N]; int color[N]; int cnt[N]; bool flag; void dfs(int u,int x){ color[u]=x; cnt[x]++; for(auto to:edge[u]){ if(color[to.fi]==-1){ dfs(to.fi,x^to.se); } else{ if((to.se==0 && color[u]!=color[to.fi]) || (to.se==1 && color[u]==color[to.fi])){ flag=false; return; } } } } int main() { int _; scanf("%d",&_); while(_--){ scanf("%d %d",&n,&m); for(int i=1;i<=n;++i) edge[i].clear(),color[i]=-1; for(int i=1;i<=m;++i){ int u,v; scanf("%d %d %s",&u,&v,s); if(!strcmp(s,"crewmate")){ edge[u].pb({v,0}); edge[v].pb({u,0}); } else{ edge[u].pb({v,1}); edge[v].pb({u,1}); } } flag=true; int ans=0; for(int i=1;i<=n;++i){ if(color[i]==-1){ cnt[0]=cnt[1]=0; dfs(i,0); ans+=max(cnt[0],cnt[1]); } } if(flag) printf("%d\n",ans); else puts("-1"); } return 0; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮