poj3207 Ikki’s Story IV – Panda’s Trick

2-SAT。

tarjan缩点。强连通分量的点要选一起选。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 20000 + 10;
const int maxm = 200000 + 10;

int n,m;
int a[maxn],b[maxn];
int g[maxn],v[maxm],next[maxm],eid;
int dfn[maxn],vis[maxn],low[maxn],vid;
int color[maxn],cid;
int s[maxn],sp;

void addedge(int a,int b) {
    v[eid]=b; next[eid]=g[a]; g[a]=eid++;
    v[eid]=a; next[eid]=g[b]; g[b]=eid++;
}

void build() {
    memset(g,-1,sizeof(g));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++) {
        scanf("%d%d",&a[i],&b[i]);
        if(a[i]>b[i]) swap(a[i],b[i]);
    }
    for(int i=1;i<=m;i++)
    for(int j=1;j<=m;j++) if(i!=j) {
        if(a[i]<a[j] && a[j]<b[i] && b[i]<b[j]) {
            addedge(i*2+1,j*2);
            addedge(j*2+1,i*2);                
        }
    }
}

void tarjan(int u) {
    dfn[u]=low[u]=++vid;
    s[++sp]=u; vis[u]=1;
    for(int i=g[u];~i;i=next[i]) {
        if(vis[v[i]]==0) {
            tarjan(v[i]);
            low[u]=min(low[u],low[v[i]]);    
        }
        else if(vis[v[i]]==1) {
            low[u]=min(low[u],dfn[v[i]]);
        }
    }
    
    if(dfn[u]==low[u]) {
        ++cid;
        do {
            color[s[sp]]=cid;
            vis[s[sp]]=2;
        }while(s[sp--]!=u); 
    }
}

void solve() {
    for(int i=2;i<=((m<<1)|1);i++) if(!vis[i]) tarjan(i);
    for(int i=1;i<=m;i++) 
        if(color[i<<1]==color[(i<<1)|1]) {
            printf("the evil panda is lying again\n");  
            return;
        }    
    printf("panda is telling the truth...\n");  
    
}

int main() {
    build();    
    solve();
    return 0;
}
posted @ 2016-07-07 20:55  invoid  阅读(147)  评论(0编辑  收藏  举报