1. 程式人生 > >BZOJ2199[Usaco2011 Jan] 奶牛議會

BZOJ2199[Usaco2011 Jan] 奶牛議會

奶牛議會

Description

由於對Farmer John的領導感到極其不悅,奶牛們退出了農場,組建了奶牛議會。議會以“每頭牛 都可以獲得自己想要的”為原則,建立了下面的投票系統: M只到場的奶牛 (1<=M<=4000) 會給N個議案投票(1<=N<=1,000) 。每隻 奶牛會對恰好兩個議案 BiandCi(1<=Bi<=N;1<=Ci<=N)投 出“是”或“否”(輸入檔案中的’Y’和’N’)。他們的投票結果分別為

VBi(VBiin{Y,N}) and VCi(VCiin{Y,N})。 最後,議案會以如下的方式決定:每隻奶牛投出的兩票中至少有一票和最終結果相符合。 例如Bessie給議案1投了贊成’Y’,給議案2投了反對’N’,那麼在任何合法的議案通過 方案中,必須滿足議案1必須是’Y’或者議案2必須是’N’(或者同時滿足)。 給出每隻奶牛的投票,你的工作是確定哪些議案可以通過,哪些不能。如果不存在這樣一個方案, 輸出”IMPOSSIBLE”。如果至少有一個解,輸出: Y 如果在每個解中,這個議案都必須通過 N 如果在每個解中,這個議案都必須駁回 ? 如果有的解這個議案可以通過,有的解中這個議案會被駁回 考慮如下的投票集合: - - - - - 議案 - - - - - 1 2 3 奶牛 1 YES NO 奶牛 2 NO NO 奶牛 3 YES YES 奶牛 4 YES YES 下面是兩個可能的解: * 議案 1 通過(滿足奶牛1,3,4) * 議案 2 駁回(滿足奶牛2) * 議案 3 可以通過也可以駁回(這就是有兩個解的原因) 事實上,上面的問題也只有兩個解。所以,輸出的答案如下: YN?

Input

第1行:兩個空格隔開的整數:N和M 第2到M+1行:第i+1行描述第i只奶牛的投票方案:Bi,VBi,Ci,VCi

Output

第1行:一個含有N個字元的串,第i個字元要麼是’Y’(第i個議案必須通過),或者是’N’ (第i個議案必須駁回),或者是’?’。 如果無解,輸出”IMPOSSIBLE”。

Sample Input

3 4 1 Y 2 N 1 N 2 N 1 Y 3 Y 1 Y 2 Y

Sample Output

YN?

題解

非常裸的2SAT,還是O(n2)的那種。

程式碼
#include<bits/stdc++.h>
using namespace std;
const int M=2005;
int ans[M],n,m;
bool vis[M];
char ch[]={'Y','N','?'};
vector<int>mmp[M];
bool dfs(int v){if(vis[v^1])return 0;if(vis[v])return 1;vis[v]=1;for(int i=mmp[v].size()-1;i>=0;--i)if(!dfs(mmp[v][i]))return 0;return 1;}
bool check(int v){memset(vis,0,sizeof(vis));return dfs(v);}
void in()
{
    int b,c,x,y;char vb[2],vc[2];
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i)scanf("%d%s%d%s",&b,vb,&c,vc),x=(b-1<<1)+(vb[0]=='Y'),y=(c-1<<1)+(vc[0]=='Y'),mmp[x^1].push_back(y),mmp[y^1].push_back(x);
}
void ac()
{
    for(int i=0,Y,N;i<n;++i)
    {
        Y=check(i<<1|1),N=check(i<<1);
        if(!Y&&!N)puts("IMPOSSIBLE"),exit(0);
        if(Y&&N)ans[i]=2;else if(!N)ans[i]=0;else ans[i]=1;
    }
    for(int i=0;i<n;++i)putchar(ch[ans[i]]);
}
int main(){in();ac();}