bzoj1823: [JSOI2010]满汉全席
2-SAT。
好像很复杂的样子所以还在慢慢摸索。。。
这道题只需要tarjan缩点就可以了,如果有一个材料的满式和汉式同时被选中,代表不可能实现。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 5000 + 10; int g[maxn],v[maxn],next[maxn],eid; int n,m,T; int dfn[maxn],low[maxn],vid; int vis[maxn]; int s[maxn],sp; int color[maxn],cid; char c1,c2; int addedge(int a,int b) { v[eid]=b; next[eid]=g[a]; g[a]=eid++; } 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); } } int main() { scanf("%d",&T); while(T--) { memset(g,-1,sizeof(g)); eid=0; scanf("%d%d",&n,&m); for(int i=1,x,y;i<=m;i++) { scanf("\n%c%d %c%d",&c1,&x,&c2,&y); x=(x<<1)+(c1=='h'); y=(y<<1)+(c2=='h'); addedge(x^1,y); addedge(y^1,x); } memset(color,0,sizeof(color)),cid=0; memset(vis,0,sizeof(vis)),vid=0; for(int i=2;i<=((n<<1)|1);i++) if(!vis[i]) tarjan(i); bool flag=true; for(int i=1;i<=n;i++) if(color[i<<1]==color[(i<<1)|1]) { flag=false; break; } if(flag) printf("GOOD\n"); else printf("BAD\n"); } return 0; }