• Knights of the Round Table


    POJ

    洛咕---SP

    洛咕---UVA

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

    分析:建原图的"补图":如果两名骑士没有憎恨关系,则在两个节点之间建立一条无向边.跑无向图(Tarjan)求出图中所有的(v-DCC),用二分图染色法判定每个(v-DCC)中是否存在奇环即可.若存在奇环,则该(v-DCC)中的所有骑士都可以参加会议(因为它们必定都在某个奇环中).

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=1005;
    const int M=1000005;
    int n,m,ans,w[N][N];
    int tot,head[N],nxt[M],to[M];
    int tim,top,cnt,root,BJ;
    int dfn[N],low[N],st[M],cut[N];
    int belong[N],visit[N],bj[N];
    vector<int>dcc[N];
    inline void add(int a,int b){nxt[++tot]=head[a];head[a]=tot;to[tot]=b;}
    inline void tarjan(int x){
    	dfn[x]=low[x]=++tim;st[++top]=x;
    	if(x==root&&!head[x]){
    		dcc[++cnt].push_back(x);
    		return;
    	}
    	int flag=0;
    	for(int i=head[x];i;i=nxt[i]){
    		int y=to[i];
    		if(!dfn[y]){
    			tarjan(y);
    			low[x]=min(low[x],low[y]);
    			if(low[y]>=dfn[x]){
    				++flag;
    				if(x!=root||flag>1)cut[x]=1;
    				++cnt;int z;
    				do{
    					z=st[top--];
    					dcc[cnt].push_back(z);
    				}while(z!=y);
    				dcc[cnt].push_back(x);
    			}
    		}
    		else low[x]=min(low[x],dfn[y]);
    	}
    }
    inline void dfs(int x,int color){
    	visit[x]=color;
    	for(int i=head[x];i;i=nxt[i]){
    		int y=to[i];
    		if(belong[y]!=belong[x])continue;
    		if(!visit[y])dfs(y,3-color);
    		else if(visit[y]==color){
    			BJ=1;return;
    		}
    	}
    }
    int main(){
    	while(1){
    		n=read();m=read();if(!n&&!m)break;
    		tot=0;ans=0;tim=0;top=0;cnt=0;
    		for(int i=1;i<=n;++i){
    			head[i]=belong[i]=0;
    			dfn[i]=low[i]=0;
    			cut[i]=bj[i]=st[i]=0;
    		}//多组数据初始化,不想用memset...
    		for(int i=1;i<=n;++i)
    			for(int j=1;j<=n;++j)w[i][j]=0;//初始化
    		for(int i=1;i<=n;++i)dcc[i].clear();//清空
    		for(int i=1;i<=m;++i){
    			int a=read(),b=read();
    			w[a][b]=w[b][a]=1;//标记憎恨关系
    		}
    		for(int i=1;i<n;++i)
    			for(int j=i+1;j<=n;++j)
    				if(!w[i][j])add(i,j),add(j,i);//建立补图
    		for(int i=1;i<=n;++i)if(!dfn[i])root=i,tarjan(i);//tarjan求v-dcc
    		for(int i=1;i<=cnt;++i){
    			for(int j=0;j<dcc[i].size();++j)
    				belong[dcc[i][j]]=i,visit[dcc[i][j]]=0;//初始化
    			BJ=0;dfs(dcc[i][0],1);//二分图染色法判定是否存在奇环
    			if(BJ){//如果存在,标记这个v-dcc内的点不用被踢出去
    				for(int j=0;j<dcc[i].size();++j)bj[dcc[i][j]]=1;
    			}
    		}
    		for(int i=1;i<=n;++i)if(!bj[i])++ans;
    		printf("%d
    ",ans);
    	}
        return 0;
    }
    
    
  • 相关阅读:
    Otter详解
    为什么要使用Netty
    haproxy实现mysql集群负载均衡
    Mysql主从复制
    java编程思想读书笔记三(HashMap详解)
    代码界的石器时代
    补码的产生与应用
    java编程思想读书笔记二(对象的创建)
    java编程思想读书笔记一(面向对象)
    Apache VFS
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11590594.html
Copyright © 2020-2023  润新知