LA 3523 Knights of the Round Table(点双连通分量+二分图判断)

来源:互联网 发布:mac 连不上appstore 编辑:程序博客网 时间:2024/05/16 12:46

题意:有n个骑士经常举行圆桌会议,商讨大事,每次圆桌会议至少应有3个骑士参加,且互相憎恨的骑士不能坐在圆桌旁的相邻位置,如果发生意见分歧,则需要举手表决,因此参加会议的骑士数目必须是奇数,以防赞同和反对票一样多,知道哪些骑士互相憎恨之后,你的任务是统计有多少个骑士不可能参加任何一个会议。


分析:求出原图的补图后,问题转化为判断一个点是否存在一个奇数环内,一个环内的所有点一定在同一个点双连通分量内,我们求出所有的点双连通分量后,判断一下它是否为一个二分图,若不是二分图则连通分量内的所有点均至少存在一个奇环内。注意对割点染色时的特殊判断。


#include <cstdio>#include <stack>#include <queue>    #include <vector>    #include <cstdio>    #include <utility>    #include <cstring>    #include <iostream>    #include <algorithm>    #define INF 0x3f3f3f3f#define MOD 1000000007using namespace std;int n,m,ans,bcc_cnt,dfs_clock,pre[1005],bccno[1005],low[1005],color[1005];bool hate[1005][1005],isans[1005];struct Edge{int u,v;Edge(int x,int y){u = x;v = y;}}; stack <Edge> S;vector <int> bcc[1005];int dfs(int u,int fa){low[u] = pre[u] = ++dfs_clock;for(int v = 1;v <= n;v++) if(!hate[u][v]) { Edge e = Edge(u,v);if(!pre[v])  {  S.push(e);  low[u] = min(low[u],dfs(v,u));  if(low[v] >= pre[u])  {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);low[u] = min(low[u],pre[v]); } } return low[u];}bool jud(int u,int colm,int edg){bool flag = true;color[u] = colm;for(int v = 1;v <= n;v++) if(!hate[u][v] && bccno[v] == edg)  if(!color[v]) flag = flag && jud(v,3-colm,edg);  else    if(color[v] != 3-colm) return false;return flag;}int main(){while(scanf("%d%d",&n,&m) == 2){if(n == 0 && m == 0) break;memset(hate,0,sizeof(hate));memset(pre,0,sizeof(pre));memset(bccno,0,sizeof(bccno));memset(isans,0,sizeof(isans));bcc_cnt = ans = 0;for(int i = 1;i <= n;i++) hate[i][i] = true;for(int i = 1;i <= m;i++){int x,y;scanf("%d%d",&x,&y);hate[x][y] = hate[y][x] = true;}for(int i = 1;i <= n;i++){dfs_clock = 0;if(!pre[i]) dfs(i,-1);}for(int i = 1;i <= bcc_cnt;i++){memset(color,0,sizeof(color));if(bcc[i].size() <= 2) continue;for(int u : bcc[i]) bccno[u] = i;bool flag = !jud(bcc[i][0],1,i);for(int u : bcc[i]) isans[u] = isans[u] || flag;}for(int i = 1;i <= n;i++)  if(isans[i]) ans++;printf("%d\n",n-ans); }}


0 0
原创粉丝点击