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; }