HDU3062 Party

题目链接:HDOJ3062

 

题目大意:

有n对夫妻被邀请参加一个聚会,因为场地的问题,每对夫妻中只有1人可以列席。在2n 个人中,某些人之间有着很大的矛盾(当然夫妻之间是没有矛盾的),有矛盾的2个人是不会同时出现在聚会上的。有没有可能会有n 个人同时列席?

 

解题思路:

tarjan缩点判断即可

 

参考代码

 1 #include <iostream>
 2 #include <cstring>
 3 #define N 2000001
 4 using namespace std;
 5 bool vis[2003];
 6 int tp,id,indx,cnt,n,m,a1,a2,c1,c2,head[2001],nxt[N],to[N],dfn[2001],low[2001],s[2001],col[2001];
 7 inline int read()
 8 {
 9     int x = 0, y = 1; char c = getchar(); while(c < '0' || c > '9') {if(c == '-') y = -1; c = getchar();} while(c >= '0' && c <= '9') x = x*10+c-'0', c = getchar(); return x*y;
10 }
11 void add(int u, int v)
12 {
13     nxt[++cnt] = head[u];
14     head[u] = cnt;
15     to[cnt] = v;
16 }
17 void tarjan(int u) // 缩点
18 {
19     dfn[u] = low[u] = ++id; s[++tp] = u; vis[u] = true;
20     for(int i = head[u]; ~i; i = nxt[i])
21     {
22         int v = to[i];
23         if(!dfn[v])
24         {
25             tarjan(v);
26             low[u] = min(low[u],low[v]);
27         } else if(vis[v]) low[u] = min(low[u],low[v]);
28     }
29     if(dfn[u] == low[u])
30     {
31         vis[u] = false;
32         col[u] = ++indx;
33         while(s[tp] != u)
34         {
35             vis[s[tp]] = false;
36             col[s[tp]] = indx;
37             tp--;
38         }
39         tp--;
40     }
41 }
42 bool solve() // 如果有一对夫妻出现在同一个scc中,则不满足条件
43 {
44     for(int i = 0; i < 2*n; i+=2) // 注意+=2
45         if(col[i] == col[i+1])
46             return true;
47     return false;
48 }
49 void init()
50 {
51     cnt = -1;
52     tp = id = indx = 0;
53     memset(head,-1,sizeof(head));
54     memset(vis,false,sizeof(vis));
55     memset(dfn,0,sizeof(dfn));
56     memset(low,0,sizeof(low));
57     memset(col,0,sizeof(col));
58     memset(nxt,0,sizeof(nxt));
59     memset(to,0,sizeof(to));
60     memset(s,0,sizeof(s));
61 }
62 int main()
63 {
64     while(~scanf("%d%d",&n,&m))
65     {
66         init();
67         for(int i = 0; i < m; i++)
68         {
69             a1 = read(); a2 = read(); c1 = read(); c2 = read();
70             add(2*a1+c1, 2*a2+1-c2); // 加边,2*a是妻子,2*a+1是丈夫
71             add(2*a2+c2, 2*a1+1-c1);
72         }
73         for(int i = 0; i < 2*n; i++)
74             if(!dfn[i])
75                 tarjan(i);
76         if(solve()) puts("NO");
77         else puts("YES");
78     }
79     return 0;
80 }

 

posted @ 2020-11-23 20:28  不敢说的梦  阅读(82)  评论(0)    收藏  举报