zoukankan      html  css  js  c++  java
  • BZOJ2215: [Poi2011]Conspiracy

    BZOJ2215: [Poi2011]Conspiracy

    https://lydsy.com/JudgeOnline/problem.php?id=3832

    分析:

    • 这题好题啊。
    • 由观察得,假设有一个合法方案想要变成另一个合法方案。这个合法方案可以用(2sat)求。
    • 不能同时将(2)个或以上的同类型人换到对面去。
    • 因此枚举所有情况判断是否能换过去。
    • (S)为完全图集合,(T)为独立集合。
    • 考虑:
      1. (S)换一个到(T)
      1. (T)换一个到(S)
      1. (S)(T)互换一个。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <vector>
    using namespace std;
    #define N 10050
    template <typename T> void chkmax(T &x,T y) {if(x<y) x=y;}
    template <typename T> void chkmin(T &x,T y) {if(y<x) x=y;}
    int n;
    bool G[N][N],g[N>>1][N>>1];
    int dfn[N],low[N],S[N],ins[N],scc,bl[N],ln,fa[N],tp;
    int tot[N],h[N];
    void tarjan(int x) {
    	int i;
    	dfn[x]=low[x]=++dfn[0]; S[++tp]=x; ins[x]=1;
    	for(i=1;i<=ln;i++) if(G[x][i]) {
    		if(!dfn[i]) {
    			tarjan(i);
    			chkmin(low[x],low[i]);
    		}else if(ins[i]) chkmin(low[x],dfn[i]);
    	}
    	if(dfn[x]==low[x]) {
    		scc++; int t=0;
    		while(t!=x) {
    			t=S[tp--]; ins[t]=0; bl[t]=scc;
    		}
    	}
    }
    int main() {
    	scanf("%d",&n); ln=n<<1;
    	int i,x,y;
    	for(i=1;i<=n;i++) {
    		scanf("%d",&x);while(x--)scanf("%d",&y),g[i][y]=1;
    	}
    	int j;
    	for(i=1;i<=n;i++) {
    		for(j=i+1;j<=n;j++) {
    			if(g[i][j]) {
    				G[i+n][j]=1;
    				G[j+n][i]=1;
    			}else {
    				G[i][j+n]=1;
    				G[j][i+n]=1;
    			}
    		}
    	}
    	for(i=1;i<=ln;i++) if(!dfn[i]) tarjan(i);
    	for(i=1;i<=n;i++) {
    		if(bl[i]==bl[i+n]) {
    			puts("0"); return 0;
    		}
    		fa[i]=bl[i]>bl[i+n];
    	}
    	int ns=0,nt=0;
    	for(i=1;i<=n;i++) {
    		if(!fa[i]) ns++;
    		else nt++;
    	}
    	int ans=ns&&nt;
    	for(i=1;i<=n;i++) {
    		for(j=1;j<=n;j++) {
    			if(g[i][j]&&fa[i]!=fa[j]) {
    				tot[i]++;
    				h[i]=j;
    			}
    		}
    		if(!fa[i]) {
    			if(tot[i]==0&&ns>1) ans++;
    		}else {
    			if(tot[i]==ns&&nt>1) ans++;
    			else {
    				for(j=1;j<=n;j++) if(!g[i][j]&&fa[i]!=fa[j]) {h[i]=j; break;}
    			}
    		}
    	}
    	for(i=1;i<=n;i++) if(fa[i]==0) {
    		for(j=1;j<=n;j++) if(fa[j]==1) {
    			if((tot[i]==0|| (tot[i]==1&&h[i]==j) ) && ((tot[j]==ns|| (tot[j]==ns-1&&h[j]==i)) ) )ans++;
    		}
    	}
    	printf("%d
    ",ans);
    }
    
  • 相关阅读:
    Android开发之旅1:环境搭建及HelloWorld
    程序员学习视频教程汇总
    Maven项目下update maven后Eclipse报错:java.lang.ClassNotFoundException: ContextLoaderL
    查看控制层从前端传来的参数
    PostMethod和GetMethod用法
    @Transient的用法和格式化页面展示的数据格式
    修改hosts
    javascript:history.go(-1)的使用
    JsonConfig的jsonConfig.setExcludes的用法
    验证登录超时,在登录后跳转超时时的页面
  • 原文地址:https://www.cnblogs.com/suika/p/10205229.html
Copyright © 2011-2022 走看看