LA 3523 圆桌骑士
題目鏈接:http://vjudge.net/contest/141787#problem/A
http://poj.org/problem?id=2942
?
此題很經典
知識點:DFS染色,點-雙連通
題意:
亞瑟王要在圓桌上召開騎士會議,為了不引發騎士之間的沖突,并且能夠讓會議的議題有令人滿意的結果,每次開會前都必須對出席會議的騎士有如下要求:
1、? 相互憎恨的兩個騎士不能坐在直接相鄰的2個位置;
2、? 出席會議的騎士數必須是奇數,這是為了讓投票表決議題時都能有結果。
?
如果出現有某些騎士無法出席所有會議(例如這個騎士憎恨所有的其他騎士),則亞瑟王為了世界和平會強制把他剔除出騎士團。
?????? 現在給定準備去開會的騎士數n,再給出m對憎恨對(表示某2個騎士之間使互相憎恨的),問亞瑟王至少要剔除多少個騎士才能順利召開會議?
?
能夠坐在一起的人,連一條邊,題目就是求所有的點中,有多少個點不在任何一個奇圈里。
這個無向圖,求出每個點雙連通分量,但是不是每個點雙連通分量都是奇圈,如果它是偶圈,那么就可以用 dfs 染色,這樣我們把每個點連通分量染色,要是染色失敗,那么這些點都可以構成奇圈,也就是說這些點都OK。最后查一遍這些點。
?
有了之前的 無向圖的割頂,橋,點-雙連通分量,DFS染色,就好寫好多了!!!
#include <bits/stdc++.h> #include <stdio.h> #include <stack> #include <algorithm> #include <string.h> #include <vector>using namespace std;const int Maxn = 1000 +10;int A[Maxn][Maxn];int pre[Maxn<<1]; bool iscut[Maxn]; int bccno[Maxn]; int dfs_clock; int bcc_cnt;vector <int> G[Maxn],bcc[Maxn];struct Edge {int u,v;Edge(int u=0,int v=0) : u(u),v(v) {} };stack <Edge> S;int dfs(int u, int fa) {int lowu = pre[u] = ++dfs_clock;int child = 0;for(int i = 0; i < G[u].size(); i++){int v = G[u][i];Edge e = (Edge){u,v};if(!pre[v]){S.push(e);child++;int lowv = dfs(v, u);lowu = min(lowu, lowv);if(lowv >= pre[u]){iscut[u] = true;bcc_cnt++;bcc[bcc_cnt].clear();for(;;){Edge x = S.top();S.pop();if(bccno[x.u] != bcc_cnt){bcc[bcc_cnt].push_back(x.u);bccno[x.u] = bcc_cnt;}if(bccno[x.v] != bcc_cnt){bcc[bcc_cnt].push_back(x.v);bccno[x.v] = bcc_cnt;}if(x.u == u && x.v == v) break;}}}else if(pre[v] < pre[u] && v != fa){S.push(e);lowu = min(lowu, pre[v]);}}if(fa < 0 && child == 1) iscut[u] = 0;return lowu; }void find_bcc(int n) {memset(pre, 0, sizeof(pre));memset(iscut, 0, sizeof(iscut));memset(bccno, 0, sizeof(bccno));dfs_clock = bcc_cnt = 0;for(int i = 0; i < n; i++)if(!pre[i]) dfs(i, -1); }int odd[Maxn], color[Maxn]; bool bipartite(int u, int b) {for(int i = 0; i < G[u].size(); i++){int v = G[u][i];if(bccno[v] != b) continue;if(color[v] == color[u]) return false;if(!color[v]){color[v] = 3 - color[u];if(!bipartite(v, b)) return false;}}return true; }int main() {int n, m;while(scanf("%d%d", &n, &m) == 2 && n){for(int i = 0; i < n; i++) G[i].clear();memset(A, 0, sizeof(A));for(int i = 0; i < m; i++){int u, v;scanf("%d%d", &u, &v);u--;v--;A[u][v] = A[v][u] = 1;}for(int u = 0; u < n; u++)for(int v = u+1; v < n; v++)if(!A[u][v]){G[u].push_back(v);G[v].push_back(u);}find_bcc(n);memset(odd, 0, sizeof(odd));for(int i = 1; i <= bcc_cnt; i++){memset(color, 0, sizeof(color));for(int j = 0; j < bcc[i].size(); j++)bccno[bcc[i][j]] = i;int u = bcc[i][0];color[u] = 1;if(!bipartite(u, i)){for(int j = 0; j < bcc[i].size(); j++)odd[bcc[i][j]] = 1;}}int ans = n;for(int i = 0; i < n; i++)if(odd[i])ans--;printf("%d\n", ans);}return 0; } View Code?
轉載于:https://www.cnblogs.com/TreeDream/p/6067635.html
新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!總結
以上是生活随笔為你收集整理的LA 3523 圆桌骑士的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Web API 接口
- 下一篇: 启动Eclipse中Tomcat遇见的错