UVALive - 3523 - Knights of the Round Table

Problem  UVALive - 3523 - Knights of the Round Table

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

For each test case you have to output a single integer on a separate line: the number of knights that have to be expelled.
 

Sample Input

5 5 1 4 1 5 2 5 3 4 4 5 0 0

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 }

猜你喜欢

转载自www.cnblogs.com/npugen/p/10746968.html