zoukankan      html  css  js  c++  java
  • 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
    ",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    Java实现稳定婚姻问题
    Java实现二分图的最大匹配
    Java实现二分图的最大匹配
    Java实现二分图的最大匹配
    Java实现二分图的最大匹配
    Java实现二分图的最大匹配
    OpenGL与Directx的区别
    为什么API多用C而不是C++,为什么C++程序大多不使用异常
    一次C#和C++的实际应用性能比较(C++允许我们使用任何手段来提高效率,只要愿意做出足够的努力)
    图形界面编程成就了C++
  • 原文地址:https://www.cnblogs.com/chadinblog/p/6553337.html
Copyright © 2011-2022 走看看