http://vjudge.net/contest/view.action?cid=48609#problem/A
Description
Input
Output
Sample Input
2 3 3 1 1 1 1 2 1 1 3 1 2 3 1 5 5 1 2 3 2 1 1 2 1 1 3 1 1 4 1 1 5 1 2 3 0
Sample Output
Case #1: no Case #2: yes
Hint
'Rock, Paper and Scissors' is a game which played by two person. They should play Rock, Paper or Scissors by their hands at the same time.
Rock defeats scissors, scissors defeats paper and paper defeats rock. If two people play the same item, the game is tied..
两个人玩“石头剪刀布”的游戏,A知道B每次都出什么,为了尽量体现公平,给A提出了两个要求,输入x,y,z,若z为1那么要求第x次和第y次A不能出一样的,若Z为0则第x次和第y次必须出一样的。在这种前提下,如果A有一次输了,或者违反了这两个要求,就算A失败,否则A胜利。
简单思路:
因为要求A一次也不能输,那么对于A来说,每一次必须与B平局或者胜利才行。所以A每次有两种选择。根据对他的要求判断第x次和第y次B出的是否一样,来确定对A的状态限制。
其实就是一个2-SAT问题,我们一般采用连通性来解决。若每一次的两种状态,在同一个强连通分量里面就不能满足2-SAT问题有解;
节点是从零开始的,2*i+1表示胜,2*i表示平,不能选负。
</pre><pre name="code" class="cpp">#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <stack> using namespace std; const int N=10205; int head[N*2],ip,dfn[N*2],low[N*2],instack[N*2],cor[N*2]; int n,m,scc,cnt,a[N*2],b[N*2][2]; struct note { int v,next; }edge[N*10]; stack<int>p; void init() { memset(head,-1,sizeof(head)); ip=0; } void addedge(int u,int v) { edge[ip].v=v,edge[ip].next=head[u],head[u]=ip++; } void tarjan(int u) { dfn[u]=low[u]=++cnt; p.push(u); instack[u]=1; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(instack[v]) { low[u]=min(low[u],dfn[v]); } } if(low[u]==dfn[u]) { ++scc; int temp; do { temp=p.top(); p.pop(); cor[temp]=scc; instack[temp]=0; }while(temp!=u); } } void solve() { while(!p.empty()) p.pop(); cnt=scc=0; memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); memset(cor,0,sizeof(cor)); memset(instack,0,sizeof(instack)); for(int i=0;i<n*2;i++) { if(!dfn[i]) tarjan(i); } } int main() { int T,tt=0; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); init(); for(int i=0;i<n;i++) { scanf("%d",&a[i]); b[i][0]=a[i]; if(a[i]==1) b[i][1]=2; if(a[i]==2) b[i][1]=3; if(a[i]==3) b[i][1]=1; } int x,y,z; for(int i=0;i<m;i++) { scanf("%d%d%d",&x,&y,&z); x--,y--; if(z) { if(b[x][0]==b[y][0]) addedge(x*2,y*2+1),addedge(y*2,x*2+1); if(b[x][0]==b[y][1]) addedge(x*2,y*2),addedge(y*2+1,x*2+1); if(b[x][1]==b[y][0]) addedge(x*2+1,y*2+1),addedge(y*2,x*2); if(b[x][1]==b[y][1]) addedge(x*2+1,y*2),addedge(y*2+1,x*2); } else { if(b[x][0]!=b[y][0]) addedge(x*2,y*2+1),addedge(y*2,x*2+1); if(b[x][0]!=b[y][1]) addedge(x*2,y*2),addedge(y*2+1,x*2+1); if(b[x][1]!=b[y][0]) addedge(x*2+1,y*2+1),addedge(y*2,x*2); if(b[x][1]!=b[y][1]) addedge(x*2+1,y*2),addedge(y*2+1,x*2); } } solve(); int flag=1; for(int i=0;i<n;i++) { if(cor[i*2]==cor[i*2+1]) { flag=0; break; } } printf("Case #%d: ",++tt); if(flag) puts("yes"); else puts("no"); } return 0; }