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;
    }
    

      

  • 相关阅读:
    HDU 2888 Check Corners (模板题)【二维RMQ】
    POJ 3264 Balanced Lineup(模板题)【RMQ】
    poj 3368 Frequent values(经典)【RMQ】
    SPOJ RPLN (模板题)(ST算法)【RMQ】
    UVA 796 Critical Links(模板题)(无向图求桥)
    UVA 315 Network (模板题)(无向图求割点)
    POJ 2029 Get Many Persimmon Trees (模板题)【二维树状数组】
    poj 3067 Japan 【树状数组】
    POJ 2481 Cows 【树状数组】
    POJ 1195 Mobile phones【二维树状数组】
  • 原文地址:https://www.cnblogs.com/chadinblog/p/6553337.html
Copyright © 2011-2022 走看看