把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

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); 
}
posted @ 2021-06-16 21:27  275307894a  阅读(30)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end