poj 2942 Knights of the Round Table

http://poj.org/problem?id=2942

题目大意:N个骑士中某些骑士之间会有仇恨。骑士们开会时围坐在一个圆桌旁。一次会议能够举行,当且仅当没有相邻的两个骑士相互仇恨,且开会人数为大于2的奇数。若某个骑士任何会议都不能参加,那么就必须将它踢出。给出骑士之间的仇恨关系,问需要踢出多少个骑士。

思路:题目给出的是一对对相互仇恨的骑士,要使得骑士间环成一环,相邻没有仇恨,就要建图的时候就不能出现相邻有仇恨的。然后问题转化成求一个图里面的奇环,而在一个双连通图里,如果存在一个奇环,则这个双连通图中的每一个点,都能在一个奇环里(很蛋疼的想法)。所以最后就是在一个双连通图里找奇环,利用正负标记可以很容易求出。

View Code
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<bitset>
#include<string>
#include<climits>
#include<cstdio>
#include<vector>
#include<utility>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define IN puts("in")
#define OUT puts("out")
#define FR(x) freopen(x,"r",stdin)
#define FW(x) freopen(x,"w",stdout)
#define MSET(x,y) memset(x,y,sizeof(x))
#define ST system("pause")
using namespace std;

const int maxn = 1005;

struct nd
{
        int u,v,next;
}edge[maxn*maxn];
int head[maxn],vis[maxn],dfn[maxn],low[maxn],st[maxn],as[maxn],flag[maxn],bs[maxn][maxn],belg[maxn],color[maxn];
int ecnt,cnt,idx,tp;
void add(int u,int v)
{
        edge[ecnt].u = u;
        edge[ecnt].v = v;
        edge[ecnt].next = head[u];
        head[u] = ecnt++;
}
int judge(int u,int f)
{
        int i,v;
        color[u] = f;
        for(i = head[u]; i != -1; i = edge[i].next)
        {
                v = edge[i].v;
                if(belg[v]==cnt)
                {
                        if(color[v]==color[u])return 1;
                        if(!color[v]&&judge(v,-f))return 1;
                }
        }
        return 0;
}
void tarjan(int pre,int u)
{
        int i,v,t,k,j;
        dfn[u] = low[u] = ++idx;
        vis[u] = 1;
        st[++tp] = u;
        for(i = head[u]; i != -1; i = edge[i].next)
        {
                v = edge[i].v;
                if(v==pre)continue;
                if(!dfn[v]){
                        tarjan(u,v);
                        low[u] = min(low[v],low[u]);
                        if(low[v]>=dfn[u]){
                                k = t = 0;
                                cnt++;
                                do{
                                        j = st[tp--];
                                        as[++k] = j;
                                        belg[j] = cnt;
                                        vis[j] = 0;
                                }while(v!=j);
                                as[++k] = u;
                                MSET(color,0);
                                if(k>=3&&judge(u,1))
                                        while(k)flag[as[k--]]=0;
                        }
                }else if(vis[v])low[u] = min(dfn[v],low[u]);
        }
}
void processing(int n,int m)
{
        int i,j,k,u,v;
        for(i = 0; i < m; ++ i)
        {
                scanf("%d %d",&u,&v);
                bs[u][v] = bs[v][u] = 0;
        }
        for(i = 1; i <= n; ++ i)
                for(j = 1 + i; j <= n; ++ j)
                        if(bs[i][j]) add(i,j),add(j,i);
        for(i = 1; i <= n; ++ i)
                if(!dfn[i])tarjan(-1,i);
        k = 0;
        for(i = 1; i <= n; ++ i)if(flag[i])k++;
        printf("%d\n",k);
}
void init()
{
        ecnt = cnt = idx = tp = 0;
        MSET(head,-1);
        MSET(vis,0);
        MSET(dfn,0);
        MSET(flag,-1);
        MSET(bs,-1);
        MSET(belg,-1);
}
int main()
{
        int n,m;
        while(scanf("%d %d",&n,&m)==2)
        {
                if(n+m==0)break;
                init();
                processing(n,m);
        }
        return 0;
}

 

 

posted on 2012-07-05 13:28  aigoruan  阅读(154)  评论(0)    收藏  举报

导航