POJ2942-Knights of the Round Table

来源:互联网 发布:制作菜单图片软件 编辑:程序博客网 时间:2024/06/06 01:46

题意:一些骑士,他们有些人之间有矛盾,现在要求选出一些骑士围成一圈,圈要满足如下条件:1.人数大于1。2.总人数为奇数。3.有仇恨的骑士不能挨着坐。问有几个骑士不能和任何人形成任何的圆圈。



有很多需要注意的点

①他给我们相互憎恨的骑士线段,我们先变成补图,也就是相连的是可以在一起坐的,不相连的是不能在一起坐的。也就是说我们

要从相连的当中找。  (先求补图)

②他让我们求的是任何搭配都不行的骑士的数量,就是说完全不能开会的,我们要遍历各种情况。

③tarjan求双联通,每求出一个双联通区,我们要先判断是否为奇数个,利用二分染色法判断判断是不是奇数个。(题目要求为奇数个人)。如果是

记录所有的成员,这些成员都不用踢出去,我们再找继续找其他的强连通图即可。


基本思路:

①我们一般做这种题,都会往tarjan上靠,对于这道题,如果我们想用tarjan来做,必然是说明部分点可以合并,也就是相互信任的点可以合并。而题目给的

是相互憎恨的,所以我们要求补图

②对于判断一个图是否为奇圈,就是用染色法判断即可。

③什么时候判断,也就是每次找出一个强连通是就要判断一次,因为这样省空间省时间。

④题目一定要读懂,是任何一个会议都不能参加的。人数要>3的。

#include <iostream>
#include <queue>
#include <string.h>
#include <stdio.h>
using namespace std;
const int maxn=1005;
const int maxm=1000005;
struct Edge
{
    int to,next;
} edge[maxm];
int head[maxn],tot;
int g[maxn][maxn];
int low[maxn],dfn[maxn],Stack[maxn],belong[maxn];
int Index,top;
int block;
bool Instack[maxn];
bool can[maxn];
bool ok[maxn];
int tmp[maxn];
int cc;
int color [maxn];
void addedge(int u,int v)
{
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
bool dfs(int u,int col)
{
    color[u]=col;
    for(int i=head[u]; i!=-1; i=edge[i].next)
    {
        int v=edge[i].to;
        if(!ok[v])
            continue;
        if(color[v]!=-1)
        {
            if(color[v]==col)
                return false;
            continue;
        }
        if(!dfs(v,!col))
            return false;
    }
    return true;


}
void tarjan(int u,int pre)
{
    int v;
    low[u]=dfn[u]=++Index;
    Stack[top++]=u;
    Instack[u]=true;
    for(int i=head[u]; i!=-1; i=edge[i].next)
    {
        v=edge[i].to;
        if(v==pre)
            continue;
        if(!dfn[v])
        {
            tarjan(v,u);
            if(low[u]>low[v])
                low[u]=low[v];
            if(low[v]>=dfn[u])
            {
                block++;
                int vn;
                cc=0;
                memset(ok,false,sizeof(ok));
                do
                {
                    vn=Stack[--top];
                    belong[vn]=block;
                    Instack[vn]=false;
                    ok[vn]=true;
                    tmp[cc++]=vn;
                }
                while(v!=vn);
                ok[u]=1;
                memset(color,-1,sizeof(color));
                if(!dfs(u,0))
                {
                    can[u]=true;
                    while(cc--)
                        can[tmp[cc]]=true;
                }
            }
        }
        else if(low[u]>dfn[v])
            low[u]=dfn[v];
    }
}
void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
    memset(g,0,sizeof(g));
    memset(low,0,sizeof(low));
    memset(can,0,sizeof(can));
    memset(dfn,0,sizeof(dfn));
    memset(Instack,false,sizeof(Instack));
    Index=block=top=0;
}


int main()
{
    int n,m,k1,k2;
    while(cin>>n>>m)
    {
        if(n==0&&m==0)
            break;
        init();
        for(int i=1; i<=m; i++)
        {
            cin>>k1>>k2;
            g[k1][k2]=g[k2][k1]=1;
        }
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
            {
                if(i!=j&&!g[i][j])
                {
                    addedge(i,j);
                }
            }
        for(int i=1; i<=n; i++)
            if(!dfn[i])
                tarjan(i,-1);
        int ans=n;
        for(int i=1; i<=n; i++)
            if(can[i])
                ans--;
        cout<<ans<<endl;
    }
    return 0;
}

阅读全文
0 0
原创粉丝点击