HDU 3062 Party
Chieh
posted @ 2015年1月04日 11:46
in HDUOJ
, 400 阅读
飞机票: http://acm.hdu.edu.cn/showproblem.php?pid=3062
开始学习2-sat了
其实2-sat原理很简单,简单来说,有2个组。每个组里有2个人。定义为A1,A2,B1,B2.如果选择A1不能选择B1。则在A1,B2连一条边,A2,B1连一条边。。。然后强联通一下。判断下A1和A2是否属于同一个块。如果是的话,那方案不可行,不是的话反之~然后这题是个入门题。把没对夫妻分为2*i和 2*i+1 然后建边,tarjan一下。。判断2*i和2*i+1是否属于同一个块即可。。。
/* Author:Chieh Grow up happy */ #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <map> #include <queue> #include <stack> #include <vector> #define LL long long using namespace std; const int maxn=2345; vector<int> V[maxn]; int n,m; void init() { for(int i=0; i<=2*n; i++)V[i].clear(); int a,b,c,d,u,v; for(int i=1; i<=m; i++) { scanf("%d%d%d%d",&a,&b,&c,&d); u=2*a+c; v=2*b+d; V[u].push_back(v^1); V[v].push_back(u^1); } } bool instack[maxn]; int dfn[maxn],low[maxn],sta[maxn],belong[maxn],indexx,scnt,cntnum; void tarjan(int u) { dfn[u]=low[u]=indexx++; instack[u]=1; sta[++scnt]=u; for(int i=0; i<V[u].size(); i++) { int v=V[u][i]; if(dfn[v]==-1) { tarjan(v); low[u]=min(low[u],low[v]); } else if(instack[v])low[u]=min(dfn[v],low[u]); } if(dfn[u]==low[u]) { for(int v=-1; v!=u; scnt--) { v=sta[scnt]; instack[v]=0; belong[v]=cntnum; } cntnum++; } } void play() { indexx=cntnum=0; scnt=-1; memset(dfn,-1,sizeof(dfn)); memset(instack,0,sizeof(instack)); for(int i=0; i<2*n; i++) { if(dfn[i]==-1)tarjan(i); } for(int i=0; i<n; i++) { if(belong[i*2]==belong[i*2+1]) { printf("NO\n"); return; } } printf("YES\n"); } int main() { while(scanf("%d%d",&n,&m)!=EOF) { init(); play(); } // cout << "Hello world!" << endl; return 0; }