1. 程式人生 > 其它 >luogu P4123 [CQOI2016]不同的最小割

luogu P4123 [CQOI2016]不同的最小割

題面傳送門
顯然我們不能爆枚點對算最小割。
然而這個東西其實可以把最小割樹跑出來然後搞。
但是因為求的是種類個數所以連最小割樹都不用建出來直接扔到一個map裡面即可。
時間複雜度\(O(n^3m)\)但是根本跑不滿。
code:

#include <vector>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
#include<bitset>
#include<set>
#include<map>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 850
#define M 8500
#define eps (1e-5)
#define mod (1<<31)
#define U unsigned int
using namespace std;
int n,m,d[N+5],nows[N+5],now,S,T,A[N+5],x,y,z,cnt,B[N+5],Bh,C[N+5],Ch;map<int,int> F;
struct yyy{int to,w,z;}tmp;
struct ljb{
	int head,h[N+5];yyy f[M+5<<2];
	I void add(int x,int y,int z){f[head]=(yyy){y,z,h[x]};h[x]=head++;}
}s,G;queue<int> Q;
I void Get(int x,int y,int z){s.add(x,y,z);s.add(y,x,0);}
I int bfs(){
	while(!Q.empty()) Q.pop();memset(d,0x3f,sizeof(d));d[S]=0;Q.push(S);nows[S]=s.h[S];
	while(!Q.empty()){
		now=Q.front();Q.pop();for(int i=s.h[now];~i;i=tmp.z){
			tmp=s.f[i];if(d[tmp.to]<1e9||!tmp.w) continue;d[tmp.to]=d[now]+1;
			Q.push(tmp.to);nows[tmp.to]=s.h[tmp.to];if(tmp.to==T) return 1;
		}
	}
	return 0;
}
I int dfs(int x,int sum){
	if(x==T) return sum;int k,pus=0,i;yyy tmp;for(i=nows[x];~i;i=tmp.z){
		tmp=s.f[i];nows[x]=i;if(!tmp.w||d[tmp.to]!=d[x]+1) continue;k=dfs(tmp.to,min(tmp.w,sum));
		if(!k) d[tmp.to]=1e9;sum-=k;pus+=k;s.f[i].w-=k;s.f[i^1].w+=k;if(!sum)break;
	}
	return pus;
}
I void build(int l,int r){
	if(l==r) return;re int i,Ans=0;S=A[l];T=A[r];s=G;while(bfs())Ans+=dfs(S,1e9);!F[Ans]&&(cnt++,F[Ans]=1);
	Bh=Ch=0;for(i=l;i<=r;i++) (d[A[i]]>1e9?B[++Bh]:C[++Ch])=A[i];for(i=l;i<=l+Bh-1;i++) A[i]=B[i-l+1];
	for(i=l+Bh;i<=r;i++) A[i]=C[i-Bh-l+1];Ans=Bh;build(l,l+Ans-1);build(l+Ans,r); 
}
int main(){
	freopen("1.in","r",stdin);
	re int i;scanf("%d%d",&n,&m);memset(s.h,-1,sizeof(s.h));for(i=1;i<=m;i++)scanf("%d%d%d",&x,&y,&z),Get(x,y,z),Get(y,x,z);
	G=s;for(i=1;i<=n;i++) A[i]=i;build(1,n);printf("%d\n",cnt); 
}