2016年ICPC亚洲区域赛大连站A题Wrestling Match

题目链接https://ac.nowcoder.com/acm/problem/124640

解题思路:深搜 + 二分图染色问题

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 vector<int> mp[1010]; //mp[i]存储i这个选手的所有出边 
 4 int n; //总选手数 
 5 int color[1010]; //存储每个选手是good还是bad 
 6 bool dfs(int p, int c) { //深搜,假设p选手是c的话,看是否有矛盾出现
 7     //有矛盾返回false,无矛盾返回true 
 8     color[p] = c;
 9     for (int i = 0 ; i < mp[p].size(); i++) { //遍历p的所有出边 
10         if (color[mp[p][i]] == c) {
11             return false;
12         }
13         if (color[mp[p][i]] == 0 && !dfs(mp[p][i], -c)) { //如果该点还没被染色,就把它染为另外一种颜色 
14             return false;
15         }
16     }
17     return true;
18 }
19 void solve() {
20     for (int i = 1; i <= n; i++) {  
21         if (color[i] == 1) { //如果该选手是good的话 
22             if (!dfs(i, 1)) {
23                 cout << "NO" << endl;
24                 return;
25             }
26         }
27     }
28     for (int i = 1; i <= n; i++) {
29         if (color[i] == -1) { //如果该选手是bad的话 
30             if (!dfs(i, -1)) {
31                 cout << "NO" << endl;
32                 return;
33             }
34         }
35     }
36     for (int i = 1; i <= n; i++) {
37         if (color[i] == 0) {
38             if (!dfs(i, 1)) {
39                 cout << "NO" << endl;
40                 return;
41             }
42         }
43     }
44     for (int i = 1; i <= n; i++) {
45         if (color[i] == -5) {
46             cout << "NO" << endl;
47             return;
48         }
49     }
50     cout << "YES" << endl;
51 }
52 int main() {
53     int m, x, y; //总边数,good选手数,bad选手数 
54     while (cin >> n >> m >> x >> y) {
55         for (int i = 1; i <= n; i++) { //每一次都要把i这个选手的所有出边清空并赋初值-5 
56             mp[i].clear();
57             color[i] = -5; //-5表示i选手的是good还是bad是未知的 
58         }
59         for (int i = 0; i < m; i++) { //遍历m场比赛 
60             int a, b;
61             cin >> a >> b; //a选手和b选手之间有场比赛 
62             color[a] = 0; //0表明该选手有比赛,需要被染色 
63             color[b] = 0; //0表明该选手有比赛,需要被染色 
64             mp[a].push_back(b); //a连向b有一条边 
65             mp[b].push_back(a); //b连向a有一条边 
66         }
67         for (int i = 0; i < x; i++) { //x个已知的good选手 
68             int t;
69             cin >> t;
70             color[t] = 1; //1表示该选手是good选手 
71         }
72         for (int i = 0; i < y; ++i) { //y个已知的bad选手 
73             int t;
74             cin >> t;
75             color[t] = -1; //-1表示该选手是bad 
76         }
77         solve(); //解决问题 
78     }
79     return 0;
80 }
原文地址:https://www.cnblogs.com/fx1998/p/13662099.html