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