BZOJ 4435 [Cerc2015]Juice Junctions 分治最小割+hash

 分治最小割的题目,要求n2.

 之前用的n3的方法自然不能用了.

 于是用hash,设hash[i][j]表示在最小割为i的时候,j是否与S联通.

 看懂这个需要理解一下最小割树的构造.

 这种题建议用EK写,因为EK在流量保证很小的时候实际是非常快的.

 另外,这题卡常.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<iomanip>
using namespace std;
#define ll long long
#define db double 
#define up(i,j,n) for(int i=j;i<=n;i++)
#define pii pair<int,int>
#define uint unsigned int
#define FILE "dealing"
int read(){
	int x=0,f=1,ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return x*f;
}
template<class T> bool cmax(T& a,T b){return a<b?a=b,true:false;}
template<class T> bool cmin(T& a,T b){return a>b?a=b,true:false;}
const int maxn=3160,limit=128,inf=1000000000;
int n,m,k,S,T,maxflow;
int q[maxn],tail=0,head=0,d[maxn],vis[maxn],r[maxn],id[maxn],pre[maxn];
unsigned long long base=1,hash[4][maxn];
struct node{
	int y,next,flow;
}e[101000];
int len=1,linkk[maxn];
void insert(int x,int y,int flow){
	e[++len].y=y;
	e[len].next=linkk[x];
	linkk[x]=len;
	e[len].flow=flow;
	e[++len].y=x;
	e[len].next=linkk[y];
	linkk[y]=len;
	e[len].flow=flow;
}
bool EK(){
	tail=head=0;
	q[++tail]=S;
	d[S]=inf;
	memset(vis,0,sizeof(vis));
	while(++head<=tail){
		int x=q[head];vis[x]=1;
		for(int i=linkk[x];i;i=e[i].next){
			if(e[i].flow&&!vis[e[i].y]){
				pre[e[i].y]=x,d[e[i].y]=min(d[x],e[i].flow);
				r[e[i].y]=i;
				vis[e[i].y]=1,q[++tail]=e[i].y;
			}
		}
	}
	if(!vis[T])return 0;
	int now=T;
	while(now!=S){
		e[r[now]].flow-=d[T];
		e[r[now]^1].flow+=d[T];
		now=pre[now];
	}
	maxflow+=d[T];
	return 1;
}
int getflow(){
	maxflow=0;
	while(EK());
	return maxflow;
}
void dfs(int x){
	vis[x]=1;
	for(int i=linkk[x];i;i=e[i].next){
		if(e[i].flow&&!vis[e[i].y])
			dfs(e[i].y);
	}
}
int tmp[maxn];
void work(int l,int r){
	if(l>=r)return;
	S=id[l],T=id[r];
	for(int i=2;i<=len;i+=2)e[i].flow=e[i^1].flow=(e[i].flow+e[i^1].flow)>>1;
	int flow=getflow();
	base*=233;
	up(i,1,n)if(!vis[i])hash[flow][i]+=base;
	memset(vis,0,sizeof(vis));dfs(S);
	int L=l,R=r;
	up(i,l,r){
		if(vis[id[i]])tmp[L++]=id[i];
		else tmp[R--]=id[i];
	}
	up(i,l,r)id[i]=tmp[i];
	work(l,L-1);
	work(R+1,r);
}
int main(){
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
	n=read(),m=read();
	up(i,1,m){
		int x=read(),y=read();
		insert(x,y,1);
	}
	up(i,1,n)id[i]=i;
	work(1,n);
	int ans=0;
	up(i,1,n)up(j,i+1,n)up(k,0,3)
		if(hash[k][i]!=hash[k][j]){ans+=k;break;}
	printf("%d\n",ans);
	return 0;
}

  

posted @ 2017-03-15 11:33  CHADLZX  阅读(171)  评论(0编辑  收藏  举报