2018-2019 ACM-ICPC, Asia Seoul Regional Contest K TV Show Game 2-sat
作者:互联网
题意:
有n个人,k盏灯,灯有红蓝两种颜色,每个人都猜了三种灯的颜色,问如何安排灯的颜色,使得每个人猜的灯至少有两个是对的。
思路:
很容易想到2-sat,但是显然枚举每个人猜对的情况是不显示的,因为猜对两个和猜对三个两种情况就很难搞了。所以我们枚举每一个人猜的灯错的是哪一盏,如果某一盏错了,那么另外两盏就必须是对的,这样才符合条件。
我们用一个light的二维vector,保存:$灯的某种颜色,选这个颜色是属于选错的人$,再用一个二维vector名字叫people保存每个人的三种错误情况。
然后在twosat的函数里枚举每种灯的颜色,如果说某一种颜色对于所有选错的人来说都满足条件(满足dfs),那对于这个灯的颜色选对的人肯定已经是更优的,所以可以这样枚举。
在dfs中check合法性的时候,就枚举所有选错的人,这个人的其他颜色都必须选对才可以。
结合文字看代码吧,光靠文字有点难表述清楚。
#pragma GCC optimize (2) #pragma G++ optimize (2) #pragma comment(linker, "/STACK:102400000,102400000") #include<bits/stdc++.h> #include<cstdio> #include<vector> #define rep(i,a,b) for(int i=a;i<=b;i++) #define dep(i,b,a) for(int i=b;i>=a;i--) #define clr(a,b) memset(a,b,sizeof(a)) #define pb push_back #define pii pair<int,int > using namespace std; typedef long long ll; const int maxn=10010; const int inf=0x3f3f3f3f; ll rd() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int vis[maxn],sta[maxn],top; struct node{ int p1,p2,p3,c1,c2,c3; }a[maxn]; vector<int >light[maxn],peo[maxn]; int n,k; bool dfs(int u){ if(vis[u^1])return false; if(vis[u])return true; vis[u]=1; sta[++top]=u; for(auto &x:light[u]){ for(auto &v:peo[x]){ if(v==u)continue; if(!dfs(v^1))return false; } } return true; } int two_sat(int n){ for(int i=2;i<=n;i+=2){ if(vis[i]||vis[i^1])continue; top=0; if(!dfs(i)){ while(top){vis[sta[top--]]=0;} if(!dfs(i^1))return false; } } return true; } int main(){ cin>>k>>n; rep(i,1,n){ char xx,yy,zz; scanf("%d %c %d %c %d %c",&a[i].p1,&xx,&a[i].p2,&yy,&a[i].p3,&zz); a[i].c1=a[i].p1*2+(xx=='B'); a[i].c2=a[i].p2*2+(yy=='B'); a[i].c3=a[i].p3*2+(zz=='B'); light[a[i].c1^1].push_back(i); peo[i].push_back(a[i].c1^1); light[a[i].c2^1].push_back(i); peo[i].push_back(a[i].c2^1); light[a[i].c3^1].push_back(i); peo[i].push_back(a[i].c3^1); } int f=two_sat(2*k); if(f==0){ puts("-1"); }else{ for(int i=1;i<=k;i++){ if(vis[i*2])putchar('R'); else putchar('B'); } puts(""); } } /* 7 5 3 R 5 R 6 B 1 B 2 B 3 R 4 R 5 B 6 B 5 R 6 B 7 B 1 R 2 R 4 R 5 6 1 B 3 R 4 B 2 B 3 R 4 R 1 B 2 R 3 R 3 R 4 B 5 B 3 B 4 B 5 B 1 R 2 R 4 R */
标签:ch,Seoul,Show,int,light,back,ACM,peo,push 来源: https://www.cnblogs.com/mountaink/p/11615502.html