BZOJ 4519 [CQOI2016]不同的最小割

这道题目很奇怪.

为什么奇怪?因为这道题用了一种叫分治最小割/最小割树的玩意.

以前从来没有见过这东西.

推荐一个讲这玩意的博客

写起来还是很顺手的.

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<string>
#include<iomanip>
#include<algorithm>
#include<map>
using namespace std;
#define ll long long
#define FILE "dealing"
#define up(i,j,n) for(int i=j;i<=n;++i)
#define db double
#define uint unsigned ll
#define eps 1e-12
#define pii pair<ll,ll>
ll read(){
	ll 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 f*x;
}
const ll maxn=20500,limit=1e6,mod=(ll)(7+1e9+0.1);
const ll inf=(ll)(1e9);
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;}
template<class T>T min(T& a,T& b){return a<b?a:b;}
template<class T>T max(T& a,T& b){return a>b?a:b;}
int n,m,S,T,id[maxn],vis[maxn],tmp[maxn],w[maxn],tot=0;
struct node{
	int y,next,flow,rev;
}e[maxn];
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].rev=len+1;
	e[++len].y=x;
	e[len].next=linkk[y];
	linkk[y]=len;
	e[len].flow=flow;
	e[len].rev=len-1;
}
int d[maxn],q[maxn],head,tail;
bool makelevel(){
	up(i,1,n)d[i]=-1;
	d[S]=0;head=tail=0;
	q[++tail]=S;
	while(++head<=tail){
		int x=q[head];
		for(int i=linkk[x];i;i=e[i].next)
			if(d[e[i].y]==-1&&e[i].flow)d[e[i].y]=d[x]+1,q[++tail]=e[i].y;
	}
	return d[T]!=-1;
}
int makeflow(int x,int flow){
	if(x==T||!flow)return flow;
	int maxflow=0,dis=0;
	for(int i=linkk[x];i&&maxflow<flow;i=e[i].next){
		if(d[e[i].y]==d[x]+1&&e[i].flow)
			if(dis=makeflow(e[i].y,min(flow-maxflow,e[i].flow))){
				e[i].flow-=dis;
				e[i^1].flow+=dis;
				maxflow+=dis;
			}
	}
	if(!maxflow)d[x]=-1;
	return maxflow;
}
int dinic(){
	int ans=0,d;
	while(makelevel())
		while(d=makeflow(S,inf))
			ans+=d;
	return ans;
}
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);
	}
}
void divide(int l,int r){
	if(l==r)return;
	for(int i=2;i<=len;i+=2)
		e[i].flow=e[i^1].flow=(e[i].flow+e[i^1].flow)>>1;
	S=id[l],T=id[r];
	int maxflow=dinic();
	w[++tot]=maxflow;
	up(i,1,n)vis[i]=0;
	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];
	divide(l,L-1);divide(R+1,r);
}
int main(){
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
	n=read(),m=read();
	up(i,1,n)id[i]=i;
	up(i,1,m){
		int x=read(),y=read(),v=read();
		insert(x,y,v);
	}
	divide(1,n);
	sort(w+1,w+tot+1);
	w[0]=-1;
	int ans=0;
	up(i,1,tot)if(w[i]!=w[i-1])ans++;
	printf("%d\n",ans);
	return 0;
}

  

posted @ 2017-03-13 19:51  CHADLZX  阅读(114)  评论(0编辑  收藏  举报