2199: [Usaco2011 Jan]奶牛议会 2-sat

链接

https://www.luogu.org/problemnew/show/P3007
https://www.lydsy.com/JudgeOnline/problem.php?id=2199

思路

建图,缩点tarjan
判断impossible
之后就不是输出方案的套路了
判断Y 、N、?
直接暴力枚举点的两种情况(i,i+n)是否能dfs到一块
不能就是互不牵制,是?
其他就是Y 或 N

代码

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+7;
int read() {
    int x=0,f=1;char s=getchar();
    for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
    for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
    return x*f;
}
int n,m;
struct node {
    int v,nxt;
}e[N<<1];
int head[N<<1],tot;
void add(int u,int v) {
    e[++tot].v=v;
    e[tot].nxt=head[u];
    head[u]=tot;
}
int stak[N],top,cnt,belong[N],low[N],dfn[N],vis[N];
void tarjan(int u) {
    low[u]=dfn[u]=++cnt;
    stak[++top]=u;
    vis[u]=1;
    for(int i=head[u];i;i=e[i].nxt) {
        int v=e[i].v;
        if(!dfn[v]) {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        } else if(vis[v]) {
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u]) {
        ++belong[0];
        while(stak[top]!=u) {
            vis[stak[top]]=0;
            belong[stak[top]]=belong[0];        
            top--;
        } top--;
        vis[u]=0;
        belong[u]=belong[0];
    }
}
vector<int> G[N];
int dfs(int u,int goal) {
    if(u==goal) return 1;
    for(vector<int>::iterator it=G[u].begin();it!=G[u].end();++it) {
        if(dfs(*it,goal)) return 1;
    }
    return 0;
}
void solve(int id) {
//  cout<<belong[id]<<" "<<belong[id+n]<<"<\n";
    int a=dfs(belong[id],belong[id+n]);
    int b=dfs(belong[id+n],belong[id]);
    if(!a&&!b) printf("?");
    if(b) printf("Y");
    if(a) printf("N");
}
int main() {
//  freopen("a.in","r",stdin);
    n=read(),m=read();
    for(int k=1;k<=m;++k) {
        //read
        //begin 
        char s;
        int i,j,x,y;
        i=read();
        s=getchar();
        while(s==' ') s=getchar();
        x= s=='Y' ? 1 : 0;
        j=read();
        s=getchar();
        while(s==' ') s=getchar();
        y= s=='Y' ? 1 : 0;
        //end
        add(n*x+i,n*(y^1)+j);
        add(n*y+j,n*(x^1)+i);
    }
    for(int i=1;i<=2*n;++i) 
        if(!dfn[i])
            tarjan(i);
    for(int i=1;i<=n;++i) {
        if(belong[i]==belong[i+n]) {
            puts("IMPOSSIBLE");
            return 0;
        }
    }
    for(int i=1;i<=2*n;++i) {
        for(int j=head[i];j;j=e[j].nxt) {
            if(belong[i]!=belong[e[j].v]) {
                G[belong[i]].push_back(belong[e[j].v]);
            }
        }
    }
    for(int i=1;i<=n;++i) solve(i);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/dsrdsr/p/10408032.html