Time Limit: 4500 mSec
Problem Description
Input
The input contains several blocks of test cases. Each case begins with a line containing two integers 1 ≤ n ≤ 1000 and 1 ≤ m ≤ 1000000. The number n is the number of knights. The next m lines describe which knight hates which knight. Each of these m lines contains two integers k1 and k2, which means that knight number k1 and knight number k2 hate each other (the numbers k1 and k2 are between 1 and n). The input is terminated by a block with n = m = 0.
Output
Sample Input
Sample Output
2
题解:双连通分量+二分图性质及判断,首先抽象出本题的模型,可以相邻而坐的骑士之间连一条边,对于简单奇环中的每一个骑士都可以参加会议,而不被任意一个简单奇环包含的骑士不能参加会议,因此此题就是统计不在任意一个简单奇环中的节点个数,做出这个题首先需要知道两个知识点
一、二分图中必定没有奇环
二、点双连通分量是满足如下性质:任意两条边都在同一个简单环中
通常来说如果要求任意两条边在同一个简单环中,那么就是求点-双连通,因此此题就相当于求完点双连通之后判断一下每个双连通分量是否是二分图,其实还需要证明一个东西就是如果该双连通分量不是二分图,那么其中每一个节点都会存在于某个奇环内,证明很简单不赘述。有了这些理论基础之后其实就是两个模板放在一起即可。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define REP(i, n) for (int i = 1; i <= (n); i++) 6 #define sqr(x) ((x) * (x)) 7 8 const int maxn = 1000 + 10; 9 const int maxm = 30 + 10; 10 const int maxs = 10000 + 10; 11 12 typedef long long LL; 13 typedef pair<int, int> pii; 14 typedef pair<double, double> pdd; 15 16 const LL unit = 1LL; 17 const int INF = 0x3f3f3f3f; 18 const LL mod = 1000000007; 19 const double eps = 1e-14; 20 const double inf = 1e15; 21 const double pi = acos(-1.0); 22 23 struct Edge 24 { 25 int u, v; 26 }; 27 28 int gra[maxn][maxn]; 29 int n, m; 30 int dfs_clock, bcc_cnt, bccno[maxn], pre[maxn], is_cut[maxn]; 31 int color[maxn], odd[maxn]; 32 vector<int> G[maxn], bcc[maxn]; 33 34 stack<Edge> S; 35 36 int dfs(int u, int fa) 37 { 38 int lowu = pre[u] = ++dfs_clock; 39 int child = 0; 40 for (auto v : G[u]) 41 { 42 Edge e = (Edge){u, v}; 43 if (!pre[v]) 44 { 45 S.push(e); 46 child++; 47 int lowv = dfs(v, u); 48 lowu = min(lowu, lowv); 49 if (lowv >= pre[u]) 50 { 51 is_cut[u] = 1; 52 bcc_cnt++; 53 bcc[bcc_cnt].clear(); 54 for (;;) 55 { 56 Edge x = S.top(); 57 S.pop(); 58 if (bccno[x.u] != bcc_cnt) 59 { 60 bcc[bcc_cnt].push_back(x.u); 61 bccno[x.u] = bcc_cnt; 62 } 63 if (bccno[x.v] != bcc_cnt) 64 { 65 bcc[bcc_cnt].push_back(x.v); 66 bccno[x.v] = bcc_cnt; 67 } 68 if (x.u == u && x.v == v) 69 { 70 break; 71 } 72 } 73 } 74 } 75 else if (pre[v] < pre[u] && v != fa) 76 { 77 S.push(e); 78 lowu = min(lowu, pre[v]); 79 } 80 } 81 if (fa < 0 && child == 1) 82 is_cut[u] = 0; 83 return lowu; 84 } 85 86 void find_bcc() 87 { 88 memset(pre, 0, sizeof(pre)); 89 memset(is_cut, 0, sizeof(is_cut)); 90 memset(bccno, 0, sizeof(bccno)); 91 dfs_clock = bcc_cnt = 0; 92 for (int i = 0; i < n; i++) 93 { 94 if (!pre[i]) 95 { 96 dfs(i, -1); 97 } 98 } 99 } 100 101 bool bipartite(int u, int cnt) 102 { 103 for (auto v : G[u]) 104 { 105 if (bccno[v] != cnt) 106 continue; 107 if (color[v] == color[u]) 108 { 109 return false; 110 } 111 if (!color[v]) 112 { 113 color[v] = 3 - color[u]; 114 if (!bipartite(v, cnt)) 115 { 116 return false; 117 } 118 } 119 } 120 return true; 121 } 122 123 int main() 124 { 125 ios::sync_with_stdio(false); 126 cin.tie(0); 127 //freopen("input.txt", "r", stdin); 128 //freopen("output.txt", "w", stdout); 129 while (cin >> n >> m && (n || m)) 130 { 131 for (int i = 0; i < n; i++) 132 { 133 bcc[i].clear(); 134 G[i].clear(); 135 } 136 memset(gra, 0, sizeof(gra)); 137 int u, v; 138 for (int i = 0; i < m; i++) 139 { 140 cin >> u >> v; 141 u--, v--; 142 gra[u][v] = gra[v][u] = 1; 143 } 144 for (int i = 0; i < n; i++) 145 { 146 for (int j = i + 1; j < n; j++) 147 { 148 if (!gra[i][j]) 149 { 150 G[i].push_back(j); 151 G[j].push_back(i); 152 } 153 } 154 } 155 find_bcc(); 156 memset(odd, 0, sizeof(odd)); 157 for (int i = 1; i <= bcc_cnt; i++) 158 { 159 for (auto v : bcc[i]) 160 { 161 bccno[v] = i; 162 } 163 memset(color, 0, sizeof(color)); 164 int u = bcc[i][0]; 165 color[u] = 1; 166 if (!bipartite(u, i)) 167 { 168 for (auto v : bcc[i]) 169 { 170 odd[v] = 1; 171 } 172 } 173 } 174 int ans = n; 175 for (int i = 0; i < n; i++) 176 { 177 if (odd[i]) 178 ans--; 179 } 180 cout << ans << endl; 181 } 182 return 0; 183 }