标签:nbsp 开始 sample output turn ++ TE tin 委员会
昨天学弟问我G题是不是2-SAT,尴尬的是我不知道那是什么,所以今天特地来学一下,先来个简单的
先看一下最经典的题HDU1814和平委员会
这道题感觉跟2-SAT(仅限我现在理解的)有关系,还感觉没啥关系
oth(x)代表和x是一个国家的那个人的编号
做法就是如果 i 和 j 是冤家那么 选 i 就要选 oth(j) ,选 j 就要选 oth(i) 然后从1~2*n开始遍历
数组 f 初始是0,1代表选中,2代表不选
对于第 i 个遇到 f[i] 是0,那么先试试 选 i ,即 f[i]=1,f[oth(i)]=2
如果选了一个那么边相连的就都要选,如果边相连是2了,说明决策不对则f[i]=2,f[oth(i)]=1,若还不行那么无解
最后把f[i]=1的 i 输出就可以了
#include<stdio.h> #include<string.h> #define rep(i,j,k) for(int i=j;i<=k;++i) #define oth(x) (x%2==0?x-1:x+1) struct s { int to,next; } edge[40005]; int head[16005]; int cnt; void add(int x,int y) { edge[cnt].to=y; edge[cnt].next=head[x]; head[x]=cnt++; } int tot; int f[16005],ff[160005]; bool paint(int x) { if(f[x]!=0) return f[x]%2; f[x]=1; f[oth(x)]=2; ff[tot++]=x; for(int i=head[x]; i!=-1; i=edge[i].next) { if(!paint(edge[i].to)) return false; } return true; } int n; bool solve() { rep(i,1,2*n) { if(f[i]) continue; tot=0; if(!paint(i)) { rep(j,0,tot-1) { f[ff[j]]=0; f[oth(ff[j])]=0; } if(!paint(oth(i))) return false; } } return true; } int main() { int m; while(scanf("%d %d",&n,&m)!=EOF) { memset(head,-1,sizeof(head)); memset(f,0,sizeof(f)); cnt=0; int x,y; rep(i,1,m) { scanf("%d %d",&x,&y);//oth(x)是x的搭档 add(x,oth(y));//选x就只能选y的搭档 add(y,oth(x)); } if(solve()) { rep(i,1,2*n) if(f[i]==1) printf("%d\n",i); } else printf("NIE\n"); } }
标签:nbsp 开始 sample output turn ++ TE tin 委员会
原文地址:https://www.cnblogs.com/noncontradiction/p/9129853.html