poj 2942 Knights of the Round Table 点双连通

来源:互联网 发布:青海网络电视台 编辑:程序博客网 时间:2024/06/05 04:44

圆桌骑士,记得小时候街机也有同名还蛮喜欢玩的游戏。


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


首先可以对不相互憎恨的骑士建边,然后找出所有的双连通分量,对于每一个双连通分量,只要有一个奇圈,连通分量李所有的人都可以参加了,这个自己画个图最直接了。


模板题,好好弄好图论基础!

#include <stdio.h>#include <string.h>#include <vector>using namespace std;#define pb push_backconst int maxn = 1005;const int maxm = 1000005;struct EDGE{int u, to, next, vis;}edge[maxm<<1];int head[maxn], hate[maxn][maxn], dfn[maxn], st[maxm], color[maxn], isodd[maxn], low[maxn];int E, time, top, btot;void newedge(int u, int to) {edge[E].to = to;edge[E].u = u;edge[E].vis = 0;edge[E].next = head[u];head[u] = E++;}int min(int a, int b) {return a > b ? b : a;}vector <int> block[maxn];void dfs(int u) {dfn[u] = low[u] = ++time;for(int i = head[u];i != -1;i = edge[i].next) {if(edge[i].vis)continue;edge[i].vis = edge[i^1].vis = 1;int to = edge[i].to;st[++top] = i;if(!dfn[to]) {dfs(to);low[u] = min(low[u], low[to]);if(low[to] >= dfn[u]) {btot++;block[btot].clear();do {int now = st[top--];block[btot].pb(now);to = edge[now].u;} while(to != u);}}elselow[u] = min(low[u], low[to]);}}int flag;void DFS(int u) {for(int i = head[u];i != -1;i = edge[i].next) {if(edge[i].vis)continue;edge[i].vis = edge[i^1].vis = 1;int to = edge[i].to;if(!color[to]) {color[to] = 3 - color[u];DFS(to);}else if(color[u] == color[to])flag = 1;}}void init() {memset(head, -1, sizeof(head));memset(dfn, 0, sizeof(dfn));memset(hate, 0, sizeof(hate));memset(isodd, 0, sizeof(isodd));E = time = top = btot = 0;}int main() {int n, m, i, j, u, to;while(scanf("%d%d", &n, &m) != -1 && n) {init();for(i = 0;i < m; i++) {scanf("%d%d", &u, &to);hate[u][to] = hate[to][u] = 1;}for(i = 1;i <= n; i++) {for(j = i+1;j <= n; j++) if(!hate[i][j]) {newedge(i, j);newedge(j, i);}}for(i = 1;i <= n; i++) if(!dfn[i])dfs(i);for(i = 1;i <= btot; i++) {if(block[i].size() == 1)continue;int now = block[i][0];u = edge[now].u;for(j = 0;j < block[i].size(); j++)edge[block[i][j]].vis = 0;memset(color, 0, sizeof(color));color[u] = 1;flag = 0;DFS(u);if(flag)for(j = 0;j < block[i].size(); j++) {now = block[i][j];isodd[edge[now].u] = isodd[edge[now].to] = 1;}}int ans = 0;for(i = 1;i <= n; i++) if(!isodd[i])ans++;printf("%d\n", ans);}return 0;}


原创粉丝点击