题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3062
题目意思:有n对夫妻被邀请参加一个聚会,因为场地的问题,每对夫妻中只有1人可以列席。在2n 个人中,某些人之间有着很大的矛盾(当然夫妻之间是没有矛盾的),有矛盾的2个人是不会同时出现在聚会上的。n 个人同时列席是否有解。
题目思路:暴力法走一遍,如果solve成功则可以;也可以tarjan缩点,用定理。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N = 2005; 4 const int M = N*N; 5 struct Edge{ 6 int v,next; 7 }edge[M]; 8 int head[N],sta[N],cnt,top; 9 bool vis[N]; 10 void init() 11 { 12 memset(head,-1,sizeof(head)); 13 memset(vis,false,sizeof(vis)); 14 memset(sta,0,sizeof(sta)); 15 cnt = top = 0; 16 } 17 void inline add(int u,int v) 18 { 19 edge[++cnt].v = v; 20 edge[cnt].next = head[u]; 21 head[u] = cnt; 22 } 23 bool dfs(int u) 24 { 25 if(vis[u^1]) return false; 26 if(vis[u]) return true; 27 vis[u] = true; 28 sta[top++] = u; 29 for(int i = head[u];i != -1;i = edge[i].next) 30 { 31 if(!dfs(edge[i].v)) return false; 32 } 33 return true; 34 } 35 bool solve(int n) 36 { 37 for(int i = 0;i < (n<<1);i += 2) 38 { 39 if(!vis[i]&&!vis[i^1]) 40 { 41 top = 0; 42 if(!dfs(i)) 43 { 44 while(top) vis[sta[--top]] = false; 45 if(!dfs(i^1)) return false; 46 } 47 } 48 } 49 return true; 50 } 51 int main() 52 { 53 int n,m; 54 while(~scanf("%d%d",&n,&m)) 55 { 56 init(); 57 for(int i = 1;i <= m; i++) 58 { 59 int a1,a2,c1,c2; 60 scanf("%d%d%d%d",&a1,&a2,&c1,&c2); 61 if(c1 == 0) a1 = (a1<<1); 62 else a1 = (a1<<1) + 1; 63 if(c2 == 0) a2 = (a2<<1); 64 else a2 = (a2<<1) + 1; 65 add(a1^1,a2); 66 add(a2^1,a1); 67 } 68 if(solve(n)) printf("YES\n"); 69 else printf("NO\n"); 70 } 71 return 0; 72 }
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using std::min; 5 const int N = 2010, M = N * N; 6 struct Edge 7 { 8 int to, nex; 9 } edge[M]; 10 int num_e; 11 int head[N]; 12 int dfn[N], low[N], scc[N], sz[N], idx, tot; 13 bool insta[N]; 14 int sta[N], top; 15 void init() { 16 num_e = 0, top = 0, idx = 0, tot = 0; 17 memset(head, 0, sizeof(head)); 18 memset(insta, 0, sizeof(insta)); 19 memset(scc, 0, sizeof(scc)); 20 memset(dfn, 0, sizeof(dfn)); 21 } 22 void add_edge(int x, int y) { 23 edge[++num_e].to = y; 24 edge[num_e].nex = head[x]; 25 head[x] = num_e; 26 } 27 void tarjan(int u) { 28 dfn[u] = low[u] = ++idx; 29 sta[++top] = u; 30 insta[u] = true; 31 for (int i = head[u]; i; i = edge[i].nex) { 32 int v = edge[i].to; 33 if (!dfn[v]) { 34 tarjan(v); 35 low[u] = min(low[u], low[v]); 36 } 37 else if (insta[v]) low[u] = min(low[u], dfn[v]); 38 } 39 if (dfn[u] == low[u]) { 40 ++tot; 41 do { 42 scc[sta[top]] = tot; 43 sz[tot]++; 44 insta[sta[top]] = false; 45 } while (sta[top--] != u); 46 } 47 } 48 49 int main() { 50 int n, m; 51 while (~scanf("%d %d", &n, &m)) { 52 init(); 53 for (int i = 0, a1, a2, c1, c2; i < m; i++) { 54 scanf("%d %d %d %d", &a1, &a2, &c1, &c2); 55 add_edge(2 * a1 + c1, 2 * a2 + 1 - c2); 56 add_edge(2 * a2 + c2, 2 * a1 + 1 - c1); 57 } 58 for (int i = 0; i < 2 * n; i++) { 59 if (!dfn[i]) tarjan(i); 60 } 61 bool ans = true; 62 for (int i = 0; i < 2 * n; i += 2) { 63 if (scc[i] == scc[i+1]) { 64 ans = false; 65 break; 66 } 67 } 68 printf("%s\n", ans ? "YES" : "NO"); 69 } 70 return 0; 71 }