POJ2942 Knights of the Round Table 点双连通分量,逆图,奇圈

题目链接:

poj2942

题意:

有n个人,能够开多场圆桌会议

这n个人中,有m对人有仇视的关系,相互仇视的两人坐在相邻的位置

且每场圆桌会议的人数仅仅能为奇书

问有多少人不能參加

解题思路:

首先构图,将全部的仇视关系视为一条边,最后再取已经得到的图的逆图,

这样图上连接的边就代表能够相邻而坐的关系

然后就是找奇圈了,首先就是要找图中的环(点双连通分量)

这个环为奇环的条件:不是二分图||这个环中的部分点属于其它奇环

这个推断能够通过将已找到的环进行dfs黑白染色推断

最后不在奇环内的总和即是答案

至于为什么要找的是点双连通分量而不是边双连通分量 能够试试这组数据:

6 8

1 4

1 5

1 6

2 4

2 5

2 6

3 6

4 5

0 0

得到的逆图是这种:

假设是电双连通分量(拆开割点)则分为(1 2 3)和(3 4 5 6)两部分

而假设是边双连通分量(去掉割边)则仅仅有(1 2 3 4  5 6 )一部分了

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1050
using namespace std;
struct node{
    int to,next;
}edge[2000500];
int head[maxn],ss;
int map[maxn][maxn];

int in[maxn],odd[maxn],temp[maxn];
int color[maxn];

int dfn[maxn],low[maxn],num;
int insta[maxn],sta[maxn],top;
int n;

void init()
{
    memset(dfn,0,sizeof(dfn));
    memset(head,-1,sizeof(head));
    memset(insta,0,sizeof(insta));
    memset(map,0,sizeof(map));
    memset(odd,0,sizeof(odd));
    top=num=ss=0;
}

void addedge(int a,int b)
{
    edge[ss]=(node){b,head[a]};
    head[a]=ss++;
}

int dfs(int u,int c)
{
    color[u]=c;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].to;
        if(!in[v])
            continue;
        if(color[v]==c)
            return 1;
        else if(color[v])
            continue;
        else if(dfs(v,3-c))
            return 1;
    }
    return 0;
}

void Tarjan(int u,int pre)
{
    dfn[u]=low[u]=++num;
    insta[u]=1;
    sta[top++]=u;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].to;
        if(v==pre)
            continue;
        if(!dfn[v])
        {
            Tarjan(v,u);
            low[u]=min(low[u],low[v]);

            if(dfn[u]<=low[v])
            {
                int s=0,d=-1;
                memset(in,0,sizeof(in));
                while(d!=v)         //注意是v   点双连通的还有一种写法,总之要注意割点能够属于多个连通分量
                {
                    d=sta[--top];
                    in[d]=1;
                    insta[d]=0;       //不能让u=0
                    temp[s++]=d;
                }
                in[u]=1;
                memset(color,0,sizeof(color));
                if(dfs(u,1))          //黑白染色判定
                {
                    odd[u]=1;
                    while(s!=0)
                        odd[temp[--s]]=1;
                }
            }
        }
        else if(insta[v])
            low[u]=min(low[u],dfn[v]);
    }
}

void solve()
{
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            Tarjan(i,-1);
    int ans=0;
    for(int i=1;i<=n;i++)
        if(!odd[i])
            ans++;
    printf("%d\n",ans);
}

int main()
{
//    freopen("in.txt","r",stdin);
    int m,a,b;
    while(scanf("%d%d",&n,&m)&&(m+n))
    {
        init();
        while(m--)
        {
            scanf("%d%d",&a,&b);
            map[a][b]=map[b][a]=1;
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(i!=j&&!map[i][j])   //取逆图
                    addedge(i,j);
        solve();
    }
    return 0;
}
时间: 2024-10-12 22:10:05

POJ2942 Knights of the Round Table 点双连通分量,逆图,奇圈的相关文章

POJ2942 Knights of the Round Table[点双连通分量|二分图染色|补图]

Knights of the Round Table Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 12439   Accepted: 4126 Description Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress, and drinking with the oth

【POJ】2942 Knights of the Round Table(双连通分量)

http://poj.org/problem?id=2942 各种逗.... 翻译白书上有:看了白书和网上的标程,学习了..orz. 强连通分量就是先找出割点,然后用个栈在找出割点前维护子树,最后如果这个是割点那么子树就都是强连通分量,然后本题求的是奇圈,那么就进行黑白染色,判断是否为奇圈即可.将不是奇圈的所有强连通分量的点累计起来即可. #include <cstdio> #include <cstring> #include <cmath> #include <

UVALive-3523 Knights of the Round Table (双连通分量+二分图匹配)

题目大意:有n个骑士要在圆桌上开会,但是相互憎恶的两个骑士不能相邻,现在已知骑士们之间的憎恶关系,问有几个骑士一定不能参加会议.参会骑士至少有3个且有奇数个. 题目分析:在可以相邻的骑士之间连一条无向边,构成一张图G.则问题变成了有几个节点不在奇圈(有奇数个节点的圈)内,并且一个点在圈内最多出现一次.如果G不连通,应该对每一个分量分别求解.奇圈上的点一定在同一个双连通分量内,要找出所有的双连通分量.但是能构成二分图的双连通分量中一定没有奇圈,不能构成二分图的双连通分量中一定含有奇圈,并且分量中所

【POJ 2942】Knights of the Round Table(双联通分量+染色判奇环)

[POJ 2942]Knights of the Round Table(双联通分量+染色判奇环) Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 11661   Accepted: 3824 Description Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress, an

POJ 2942 - Knights of the Round Table(双连通图 Tarjan + 二分判定)

POJ 2942 - Knights of the Round Table(双连通图 Tarjan + 二分判定) ACM 题目地址: POJ 2942 - Knights of the Round Table 题意: 有N个骑士,给出某些骑士之间的仇恨关系,骑士们开会时会围坐在一个圆桌旁.一次会议能够顺利举行,要满足两个条件: 任意相互憎恨的两个骑士不能相邻 开会人数为大于2的奇数 若某个骑士任何会议都不能参加,那么就必须将他踢出,给出骑士之间的仇恨关系,问最少需要踢出多少个骑士? 分析: 把

UvaLive3523 Knights of the Round Table(点双联通分量+二分图染色)

UvaLive3523 Knights of the Round Table 参考了Kuangbin巨的题解. /* POJ 2942 Knights of the Round Table 亚瑟王要在圆桌上召开骑士会议,为了不引发骑士之间的冲突, 并且能够让会议的议题有令人满意的结果,每次开会前都必须对出席会议的骑士有如下要求: 1. 相互憎恨的两个骑士不能坐在直接相邻的2个位置: 2. 出席会议的骑士数必须是奇数,这是为了让投票表决议题时都能有结果. 注意:1.所给出的憎恨关系一定是双向的,不

UVA 1364 - Knights of the Round Table(双连通+二分图判定)

UVA 1364 - Knights of the Round Table 题目链接 题意:有n个圆桌骑士,知道一些骑士互相憎恨,现在要开圆桌会议,每次最少3个人,必须是奇数人数,并且互相憎恨的骑士不能在相邻,问有多少骑士是一次都无法参加的 思路:把每个骑士可以相邻的连边,然后做双连通分量,然后对于每个连通分量,利用二分图染色判定去判断是否是奇圈 代码: #include <cstdio> #include <cstring> #include <vector> #in

poj 2942 Knights of the Round Table 【双连通缩点+判奇圈】【经典】

题目:poj 2942 Knights of the Round Table 题意:n个骑士经常一起开会,其中有一些两两相互憎恨,他们不能同一桌,开会要表决一些事情,所以必须奇数个人,最少3个,求永远也参加不了会议的人的个数. 分析:这个题目两点 首先,建图求双连通缩点 建图的话,因为相互憎恨的不能再一块,所以要建补图,让能够在一起的所有的连接,这样的话,如果能存在环且环上的点是奇数个的话就可以参加会议,标记求不能参加的即可. 建好图之后用tarjan算法双连通缩点,把在一个环上的点保存起来.

poj2942 Knights of the Round Table

好久之前就注册了一直没写 今天开始把刷的题都放在上面 这个题就是建个补图找双连通分量然后染色判断是不是二分图(奇圈一定不是二分图) re了好多次 debug2小时 最后发现栈数组开小了... #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<vector> using namespace std; const int maxn=10