题目描述
(原英文题面见洛谷)
由于对Farmer John的领导感到极其不悦,奶牛们退出了农场,组建了奶牛议会。
议会以“每头牛 都可以获得自己想要的”为原则,建立了下面的投票系统: M只到场的奶牛 (1 <= M <= 4000) 会给N个议案投票(1 <= N <= 1,000) 。每只 奶牛会对恰好两个议案 B_i and C_i (1 <= B_i <= N; 1 <= C_i <= N)投 出“是”或“否”(输入文件中的’Y’和’N’)。
他们的投票结果分别为VB_i (VB_i in {‘Y’, ‘N’}) and VC_i (VC_i in {‘Y’, ‘N’})。 最后,议案会以如下的方式决定:每只奶牛投出的两票中至少有一票和最终结果相符合。 例如Bessie给议案1投了赞成’Y’,给议案2投了反对’N’,那么在任何合法的议案通过 方案中,必须满足议案1必须是’Y’或者议案2必须是’N’(或者同时满足)。
给出每只奶牛的投票,你的工作是确定哪些议案可以通过,哪些不能。
如果不存在这样一个方案, 输出”IMPOSSIBLE”。
如果至少有一个解,输出: Y 如果在每个解中,这个议案都必须通过 N 如果在每个解中,这个议案都必须驳回 ? 如果有的解这个议案可以通过,有的解中这个议案会被驳回
输入格式:
- Line 1: Two space-separated integers: N and M
- Lines 2..M+1: Line i+1 describes cow i’s votes with four
space-separated fields – an integer, a vote, another integer, and another vote: B_i, VB_i, C_i, VC_i
输出格式:
- Line 1: A string with N characters, where the ith character is either a ‘Y’ if the ith bill must pass, an ‘N’ if the ith bill must fail, or a ‘?’ if it cannot be determined whether the bill passes from these votes.
If there is no solution which satisfies every cow, then output the single line ‘IMPOSSIBLE’.
题目分析
一道比较特殊的2-SAT
2-SAT—详解
限制条件是最基本的或形式,就不再讲了
这题的方案输出看起来很麻烦
但其实远比想象的简单
tarjan求SCC后缩点
直接枚举每个点(议案)的两种状态
然后从表示该状态的结点(col[i]和col[i+n])出发深搜并标记访问到的点
最后检测是否有
col[i]
c
o
l
[
i
]
与
col[i+n]
c
o
l
[
i
+
n
]
都被访问到即可
虽然实测不缩点直接深搜也可以过
但理论上的时间复杂度是不对的
可以被特殊数据hack
#include<iostream>
#include<stack>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long lt;
int read()
{
int f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
const int maxn=4010;
int n,m;
struct node{int v,nxt;}E[2][maxn<<1];
int head[2][maxn],tot[2];
int low[maxn],dfn[maxn],cnt;
int col[maxn],ins[maxn],colnum;
int st[maxn],top;
int vis[maxn];
char s1[5],s2[5],ans[maxn];
void add(int u,int v,int d)
{
E[d][++tot[d]].nxt=head[d][u];
E[d][tot[d]].v=v;
head[d][u]=tot[d];
}
void dfs(int u)
{
vis[u]=1;
for(int i=head[1][u];i;i=E[1][i].nxt)
if(!vis[E[1][i].v]) dfs(E[1][i].v);
}
void tarjan(int u)
{
low[u]=dfn[u]=++cnt;
st[++top]=u; ins[u]=1;
for(int i=head[0][u];i;i=E[0][i].nxt)
{
int v=E[0][i].v;
if(!dfn[v]){tarjan(v);low[u]=min(low[u],low[v]);}
else if(ins[v])low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
colnum++;
do{
ins[st[top]]=0;
col[st[top]]=colnum;
}while(st[top--]!=u);
}
}
int check(int u)
{
memset(vis,0,sizeof(vis));
dfs(u);
for(int i=1;i<=n;++i)
if(vis[col[i]]&&vis[col[i+n]])return 0;
return 1;
}
int main()
{
n=read();m=read();
for(int i=1;i<=m;++i)//N-0,Y-1
{
int u=read(); scanf("%s",&s1);
int v=read(); scanf("%s",&s2);
if(s1[0]=='Y')
{
if(s2[0]=='N')add(u,v,0),add(v+n,u+n,0);
else if(s2[0]=='Y')add(u,v+n,0),add(v,u+n,0);
}
else if(s1[0]=='N')
{
if(s2[0]=='N')add(u+n,v,0),add(v+n,u,0);
else if(s2[0]=='Y')add(u+n,v+n,0),add(v,u,0);
}
}
for(int i=1;i<=n<<1;++i)
if(!dfn[i])tarjan(i);
for(int u=1;u<=n<<1;++u)
for(int i=head[0][u];i;i=E[0][i].nxt)
{
int v=E[0][i].v;
if(col[u]==col[v])continue;
add(col[u],col[v],1);
}
for(int i=1;i<=n;++i)
{
int p=check(col[i]),q=check(col[i+n]);
if(!p&&!q){printf("IMPOSSIBLE");return 0;}
else if(p&&q)ans[i]='?';
else if(p&&!q)ans[i]='N';
else if(!p&&q)ans[i]='Y';
}
for(int i=1;i<=n;++i)
cout<<ans[i];
return 0;
}