BZOJ2229:[Zjoi2011]最小割 最小割树
BZOJ2144:跳跳棋 LCA

BZOJ1143:[CTSC2008]祭祀river(&&BZOJ2718) 二分图

shinbokuow posted @ Jan 28, 2015 06:02:32 PM in BZOJ with tags 二分图 , 1334 阅读

思路:

首先是一个DAG.

然后,你要选出最多的点,使得任意两个点之间不能有到达关系.

考虑将拓扑图划分为若干条点不相交路径,那么所有的结束点之间都是不能到达的.

那么我们就要求出DAG的最小路径覆盖.

然而事实上由于是DAG,路径的点是可以相交的.于是我们通过拆点转化为一般的点不相交最小路径覆盖.

考虑给每一个点找一个入点,那么每出现一个匹配,路径的数目就会减少1.

于是利用总点数减去最大匹配即可.

#define _CRT_SECURE_NO_WARNINGS

#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<algorithm>

#define INF 0x3f3f3f3f

#define N 210
struct MaxflowSolver{
	static const int V=N<<1;
	static const int E=N*N<<1;
	int head[V],next[E],end[E],flow[E],ind;
	int d[V],gap[V],stk[V],top,cur[V];
	inline void reset(){ind=top=0,memset(head,-1,sizeof head);}
	inline void addedge(int a,int b,int f){int q=ind++;end[q]=b,next[q]=head[a],head[a]=q,flow[q]=f;}
	inline void make(int a,int b,int f){addedge(a,b,f),addedge(b,a,0);}
	inline void bfs(int T){
		static int q[V];int fr=0,ta=0;
		memset(d,-1,sizeof d),memset(gap,0,sizeof gap),++gap[d[T]=0],q[ta++]=T;
		while(fr^ta){
			int i=q[fr++];for(int j=head[i];j!=-1;j=next[j])if(d[end[j]]==-1)++gap[d[end[j]]=d[i]+1],q[ta++]=end[j];
		}
	}
	inline int Maxflow(int S,int T,int cnt){
		int res=0,u=S,i,Min,ins;bfs(T),memcpy(cur,head,sizeof cur);
		while(d[S]<cnt){
			if(u==T){
				for(Min=INF,i=0;i<top;++i)if(flow[stk[i]]<Min)Min=flow[stk[i]],ins=i;
				for(res+=Min,i=0;i<top;++i)flow[stk[i]]-=Min,flow[stk[i]^1]+=Min;
				u=end[stk[top=ins]^1];
			}
			if(u!=T&&!gap[d[u]-1])break;
			bool find=0;
			for(int&j=cur[u];j!=-1;j=next[j])if(flow[j]&&d[u]==d[end[j]]+1){find=1,ins=j;break;}
			if(find)cur[u]=stk[top++]=ins,u=end[ins];
			else{
				Min=cnt;for(int j=head[u];j!=-1;j=next[j])if(flow[j]&&d[end[j]]<Min)Min=d[end[j]],cur[u]=j;
				if(!--gap[d[u]])break;++gap[d[u]=Min+1];
				if(u!=S)u=end[stk[--top]^1];
			}
		}return res;
	}
}SteinsGate;

int head[N],next[N*N],end[N*N];
inline void addedge(int a,int b){static int q=1;end[q]=b,next[q]=head[a],head[a]=q++;}

int seq[N],cnt;bool vis[N];
void dfs(int x){
	vis[x]=1,seq[++cnt]=x;
	for(int j=head[x];j;j=next[j])if(!vis[end[j]])dfs(end[j]);
}
int main(){
	int n,m;scanf("%d%d",&n,&m);register int i,j;
	int a,b;while(m--)scanf("%d%d",&a,&b),addedge(a,b);

	SteinsGate.reset();
	for(i=1;i<=n;++i){
		memset(vis,0,sizeof vis);
		cnt=0,dfs(i);
		for(j=1;j<=cnt;++j)if(seq[j]!=i)SteinsGate.make(i,n+seq[j],1);
	}

	int S=0,T=2*n+1;
	for(i=1;i<=n;++i)SteinsGate.make(0,i,1);
	for(i=1;i<=n;++i)SteinsGate.make(n+i,T,1);

	printf("%d",n-SteinsGate.Maxflow(S,T,2*n+2));

#ifndef ONLINE_JUDGE
	system("pause");
#endif
	return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter