• # bzoj2215: [Poi2011]Conspiracy 2-sat


    bzoj2215: [Poi2011]Conspiracy 2-sat

    链接

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

    思路

    一个点的属性为去当同谋者和后勤两种
    求出一种方案来很简单(只需要用简单的2-sat)
    我们发现一条特别重要的性质:
    一个方案只会由已经求出的其他任意一种方案改变一方的一个人得来
    (基本看出来就稳了)
    因为两个人不能同时过去(显然)
    那么我们先求出一种方案
    然后统计ok[i],表示i到对面冲突的点的个数
    显然只有几种情况(大力分情况讨论)
    ①.一个间谍去后勤
    ②.一个后勤区去间谍
    就是ok==0的个数(注意双方都不能为0个人)
    ③.间谍和后勤互换(容易发现交换的两个人一定一个是0,一个是1)
    好了。

    错误

    tarjan求方案的方向居然写反了、、、
    还有mp的i+n没减n

    代码

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #define iter vector<int>::iterator
    const int N=5007;
    using namespace std;
    int read() {
    	int x=0,f=1;char s=getchar();
    	for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
    	for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
    	return x*f;
    }
    int n,ok[N<<1],dsr;
    bool mp[N][N];
    vector<int> ans[2];
    struct node {
    	int v,nxt;
    }e[N*N];
    int head[N<<1],tot;
    void add(int u,int v) {
    	e[++tot].v=v;
    	e[tot].nxt=head[u];
    	head[u]=tot;
    }
    int dfn[N<<1],low[N<<1],stak[N<<1],top,cnt,belong[N<<1],vis[N<<1];
    void tarjan(int u) {
    	dfn[u]=low[u]=++cnt;
    	vis[u]=1;
    	stak[++top]=u;
    	for(int i=head[u];i;i=e[i].nxt) {
    		int v=e[i].v;
    		if(!dfn[v]) {
    			tarjan(v);
    			low[u]=min(low[u],low[v]);
    		} else if(vis[v]) {
    			low[u]=min(low[u],dfn[v]);
    		}
    	}
    	if(low[u]==dfn[u]) {
    		belong[0]++;
    		while(stak[top]!=u) {
    			vis[stak[top]]=0;
    			belong[stak[top]]=belong[0];
    			top--;
    		} top--;
    		vis[u]=0;
    		belong[u]=belong[0];
    	}
    }
    int main() {
    	n=read();
    	for(int i=1;i<=n;++i) {
    		int k=read();
    		for(int j=1;j<=k;++j) mp[i][read()]=1;
    	}
    	for(int i=1;i<=n;++i) {
    		for(int j=1;j<i;++j) {
    			if(mp[i][j]) {
    				add(i,j+n),add(j,i+n);
    			} else {
    				add(i+n,j),add(j+n,i);
    			}
    		}
    	}
    	for(int i=1;i<=n+n;++i)
    		if(!dfn[i])
    			tarjan(i);
    	for(int i=1;i<=n;++i) {
    		if(belong[i]==belong[i+n]) {
    			puts("0");
    			return 0;
    		}
    	}
    	for(int i=1;i<=n;++i) {
    		if(belong[i] < belong[i+n]) ans[0].push_back(i);
    		else ans[1].push_back(i+n);
    	}
    	if(ans[0].size()&&ans[1].size()) dsr++;
    	for(iter i=ans[0].begin();i!=ans[0].end();++i) {
    		for(iter j=ans[1].begin();j!=ans[1].end();++j) {
    			if(!mp[*i][*j-n]) ok[*i]++;		
    		}
    	}
    	for(iter i=ans[1].begin();i!=ans[1].end();++i) {
    		for(iter j=ans[0].begin();j!=ans[0].end();++j) {
    			if(mp[*i-n][*j]) ok[*i]++;
    		}
    	}
    	int siz_0[2]={};
    	for(int k=0;k<=1;++k)
    		for(iter i=ans[k].begin();i!=ans[k].end();++i)
    			if(!ok[*i]) siz_0[k]++;
    	if(ans[0].size()>1) dsr+=siz_0[0];
    	if(ans[1].size()>1) dsr+=siz_0[1];
    	for(iter i=ans[0].begin();i!=ans[0].end();++i) {
    		if(ok[*i]==1) {
    			for(iter j=ans[1].begin();j!=ans[1].end();++j) {
    				if(!mp[*i][*j-n]&&!ok[*j]) dsr++;
    			}
    		}
    	}
    	for(iter i=ans[1].begin();i!=ans[1].end();++i) {
    		if(ok[*i]==1) {
    			for(iter j=ans[0].begin();j!=ans[0].end();++j) {
    				if(mp[*i-n][*j]&&!ok[*j]) dsr++;
    			}
    		}
    	}
    	printf("%d
    ",dsr);
    	return 0;
    }
    
  • 相关阅读:
    Docker01 centos系统安装、centos安装docker、docker安装mongoDB
    WebFlux03 SpringBoot WebFlux实现CRUD
    WebFlux02 SpringBoot WebFlux项目骨架搭建
    WebFlux01 webflux概念、异步servlet、WebFlux意义
    ReactiveStream03
    ReactiveStream02
    ReactiveStream01
    Stream03
    python爬虫2
    python爬虫1
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/10490147.html
Copyright © 2020-2023  润新知