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