Codeforces Round #747 (Div. 2) D题
Posted 佐鼬Jun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #747 (Div. 2) D题相关的知识,希望对你有一定的参考价值。
D. The Number of Imposters
题目链接: link.
题意:
给 N N N个人,每个人都有可能是好人或者坏人,现在又 M M M句话,每句话都是都是 i , j , s t r i,j,str i,j,str的形式就是指第 i i i个人说 j j j号是好人或者坏人。好人说真话,坏人说假话,现在问,在有这些逻辑关系下,坏人最多有多少个。
思路:
这个题类似于
2
−
s
a
t
2-sat
2−sat问题,对于一个连通块内,如果你确认一个人的好坏身份,那么此时整个连通块的好坏身份都将通过逻辑关系推断出来,也就是说,对于每个连通块都可以给其中一个点赋值(附上好坏关系),然后通过染色法,来求出整个连通块的好坏关系,由于好坏是对称的,所以取最大值,就是坏人的最大值。
u
说
v
是
好
的
u说v是好的
u说v是好的,那么u和v就是同种关系,同好同坏
u
说
v
是
坏
的
u说v是坏的
u说v是坏的,那么就是相反关系
通过染色法,对于每个连通块中的一个点赋值,并跑
d
f
s
dfs
dfs来染色,如果出现矛盾即如果无穷小,最后输出-1即可
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int h[N],e[2*N],w[2*N],ne[2*N],idx;
int color[N];
int n,m;
char str[20];
int ans1,ans2;
int res;
void clear_graph() {
memset(h,-1,(n+1)*4);
memset(color,-1,(n+1)*4);
idx=0;
}
void add_edge(int a,int b,int c) {
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int c) {
color[u]=c;
if(c==0) ans1++;
else ans2++;
for(int i=h[u];~i;i=ne[i]) {
int j=e[i];
if(color[j]==-1) {
dfs(j,c^w[i]);
}
else {
if((color[j]^color[u])!=w[i]) {
res=-99999999;
}
}
}
}
int main() {
int T;
cin>>T;
while(T--) {
res=0;
scanf("%d%d",&n,&m);
clear_graph();
for(int i=1,u,v;i<=m;i++) {
scanf("%d%d",&u,&v);
scanf("%s",str);
if(str[0]=='i') {
add_edge(u,v,1);
add_edge(v,u,1);
}
else {
add_edge(u,v,0);
add_edge(v,u,0);
}
}
for(int i=1;i<=n;i++) {
if(color[i]==-1) {
ans1=0,ans2=0;
dfs(i,0);
res+=max(ans1,ans2);
}
}
if(res<0) printf("-1\\n");
else printf("%d\\n",res);
}
return 0;
}
To be continued
如果你有任何建议或者批评和补充,请留言指出,不胜感激
以上是关于Codeforces Round #747 (Div. 2) D题的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #747 (Div. 2)B. Special Numbers
Codeforces Round #747 (Div. 2)B. Special Numbers
A. Consecutive Sum Riddle( Codeforces Round #747 (Div. 2))
Codeforces Round #747 (Div. 2) D题