hdu 3062 Party 2-SAT

题目链接:HDU - 3062

有n对夫妻被邀请参加一个聚会,因为场地的问题,每对夫妻中只有1人可以列席。在2n 个人中,某些人之间有着很大的矛盾(当然夫妻之间是没有矛盾的),有矛盾的2个人是不会同时出现在聚会上的。有没有可能会有n 个人同时列席?
Input
n: 表示有n对夫妻被邀请 (n<= 1000)
m: 表示有m 对矛盾关系 ( m < (n - 1) * (n -1))
在接下来的m行中,每行会有4个数字,分别是 A1,A2,C1,C2
A1,A2分别表示是夫妻的编号
C1,C2 表示是妻子还是丈夫 ,0表示妻子 ,1是丈夫
夫妻编号从 0 到 n -1
Output
如果存在一种情况 则输出YES
否则输出 NO 
题目描述:中文题目,如上所述。
算法分析:2-SAT的入门题,如果u和v有矛盾,选u的同时必须选v^1,选v的同时只能选择u^1,然后缩点判断即可。
  1 #include<iostream>

  2 #include<cstdio>

  3 #include<cstring>

  4 #include<cstdlib>

  5 #include<cmath>

  6 #include<algorithm>

  7 #include<queue>

  8 #include<vector>

  9 #include<stack>

 10 using namespace std;

 11 const int maxn=2000+10;

 12 const int M=1000000+10;

 13 

 14 int n,m;

 15 struct node

 16 {

 17     int v,next;

 18 }edge[M*4];

 19 int head[maxn],edgenum;

 20 int dfn[maxn],low[maxn],scc[maxn],ind[maxn],vis[maxn];

 21 stack<int> S;

 22 int color[maxn],f[maxn];

 23 int dfs_clock,scc_cnt;

 24 vector<int> dag[maxn];

 25 void add(int u,int v)

 26 {

 27     edge[edgenum].v=v ;edge[edgenum].next=head[u] ;

 28     head[u]=edgenum++;

 29 }

 30 void init()

 31 {

 32     memset(head,-1,sizeof(head));

 33     memset(vis,0,sizeof(vis));

 34     memset(dfn,0,sizeof(dfn));

 35     memset(ind,0,sizeof(ind));

 36     memset(color,0,sizeof(color));

 37     edgenum=dfs_clock=scc_cnt=0;

 38 }

 39 void tarjan(int u)

 40 {

 41     dfn[u]=low[u]= ++dfs_clock;

 42     vis[u]=1;

 43     S.push(u);

 44     for (int i=head[u] ;i!=-1 ;i=edge[i].next)

 45     {

 46         int v=edge[i].v;

 47         if (!dfn[v])

 48         {

 49             tarjan(v);

 50             low[u]=min(low[u],low[v]);

 51         }

 52         else if (vis[v])

 53             low[u]=min(low[u],dfn[v]);

 54     }

 55     if (low[u]==dfn[u])

 56     {

 57         scc_cnt++;

 58         while (true)

 59         {

 60             int v=S.top() ;S.pop() ;

 61             vis[v]=0;

 62             scc[v]=scc_cnt;

 63             if (u==v) break;

 64         }

 65     }

 66 }

 67 void buildDag(int n)

 68 {

 69     for (int u=0 ;u<2*n ;u++)

 70     {

 71         for (int i=head[u] ;i!=-1 ;i=edge[i].next)

 72         {

 73             int v=edge[i].v;

 74             if (scc[v] != scc[u])

 75             {

 76                 dag[scc[v]].push_back(scc[u]);

 77                 ind[scc[u]]++;

 78             }

 79         }

 80     }

 81 }

 82 void topsort()

 83 {

 84     queue<int> Q;

 85     for (int i=1 ;i<=scc_cnt ;i++) if (!ind[i]) Q.push(i);

 86     while (!Q.empty())

 87     {

 88         int u=Q.front() ;Q.pop();

 89         if (!color[u]) color[u]=1,color[f[u]]=2;

 90         for (int i=0 ;i<(int)dag[u].size() ;i++)

 91         {

 92             int v=dag[u][i];

 93             ind[v]--;

 94             if (!ind[v]) Q.push(v);

 95         }

 96     }

 97 }

 98 void solve(int n)

 99 {

100     int flag=0;

101     for (int i=0 ;i<2*n ;i++) if (!dfn[i]) tarjan(i);

102     for (int i=0 ;i<n ;i++)

103     {

104         if(scc[2*i]==scc[(2*i)^1])

105         {

106             printf("NO\n");

107             flag=1;

108             return ;

109         }

110         //else f[scc[i]]=scc[i+1],f[scc[i+1]]=scc[i];

111     }

112     if (!flag) printf("YES\n");

113 //    for (int i=0 ;i<=scc_cnt ;i++) dag[i].clear();

114 //    buildDag(n);

115 //    topsort();

116     return ;

117 }

118 int main()

119 {

120     while (scanf("%d%d",&n,&m)!=EOF)

121     {

122         init();

123         int a,b,c,d;

124         for (int i=0 ;i<m ;i++)

125         {

126             scanf("%d%d%d%d",&a,&b,&c,&d);

127             int u=2*a+c,v=2*b+d;

128             add(u,v^1) ;add(v,u^1);

129         }

130         solve(n);

131     }

132     return 0;

133 }

 

你可能感兴趣的:(part)