好神仙……最小割树是个什么东西……
其实我觉得干脆直接$O(n^2)$跑几个dinic算了……
来说一下这个叫最小割树的神奇东西
我们先建一个$n$个点,没有边的无向图
在原图中任选两点$s,t$,然后跑一遍最小割。那么在残量网络上的点会分成两个集合,一个属于$s$,一个属于$t$
我们在无向图中连接$s,t$两点,边权为最小割
然后分别对$s$的点集和$t$的点集递归做以上过程,直到生成一棵树
那么原图中任意两点的最小割就是他们树上路径的最小值
证明?(能用就好要什么证明)
感性理解一下吧……
因为题目只要求不同的最小割的个数
那么只要用一个set存一下就好了
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 #include<set> 7 #include<queue> 8 #define inf 0x3f3f3f3f 9 using namespace std; 10 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 11 char buf[1<<21],*p1=buf,*p2=buf; 12 inline int read(){ 13 #define num ch-'0' 14 char ch;bool flag=0;int res; 15 while(!isdigit(ch=getc())) 16 (ch=='-')&&(flag=true); 17 for(res=num;isdigit(ch=getc());res=res*10+num); 18 (flag)&&(res=-res); 19 #undef num 20 return res; 21 } 22 const int N=1005,M=20005; 23 int head[N],Next[M],ver[M],edge[M],ee[M],tot=1; 24 int dep[N],cur[N],vis[N],n,m,s,t; 25 queue<int> q;set<int> S; 26 inline void add(int u,int v,int e){ 27 ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=ee[tot]=e; 28 ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=ee[tot]=e; 29 } 30 inline void clear(){ 31 for(int i=2;i<=tot;++i) edge[i]=ee[i]; 32 } 33 bool bfs(){ 34 while(!q.empty()) q.pop(); 35 for(int i=1;i<=n;++i) cur[i]=head[i]; 36 memset(dep,-1,sizeof(dep)); 37 q.push(s),dep[s]=0; 38 while(!q.empty()){ 39 int u=q.front();q.pop(); 40 for(int i=head[u];i;i=Next[i]){ 41 int v=ver[i]; 42 if(dep[v]<0&&edge[i]){ 43 dep[v]=dep[u]+1,q.push(v); 44 if(v==t) return true; 45 } 46 } 47 } 48 return false; 49 } 50 int dfs(int u,int limit){ 51 if(u==t||!limit) return limit; 52 int flow=0,f; 53 for(int i=cur[u];i;cur[u]=i=Next[i]){ 54 int v=ver[i]; 55 if(dep[v]==dep[u]+1&&(f=dfs(v,min(limit,edge[i])))){ 56 flow+=f,limit-=f; 57 edge[i]-=f,edge[i^1]+=f; 58 if(!limit) break; 59 } 60 } 61 return flow; 62 } 63 int dinic(){ 64 int flow=0; 65 while(bfs()) flow+=dfs(s,inf); 66 return flow; 67 } 68 void find(int u){ 69 vis[u]=1; 70 for(int i=head[u];i;i=Next[i]){ 71 int v=ver[i]; 72 if(!vis[v]&&edge[i]) find(v); 73 } 74 } 75 void check(){ 76 clear(); 77 S.insert(dinic()); 78 memset(vis,0,sizeof(vis)); 79 find(s); 80 } 81 int p[N]; 82 int main(){ 83 //freopen("testdata.in","r",stdin); 84 n=read(),m=read(); 85 for(int i=1;i<=m;++i){ 86 int u=read(),v=read(),e=read();add(u,v,e); 87 } 88 for(int i=2;i<=n;++i) p[i]=1; 89 for(int i=2;i<=n;++i){ 90 s=i,t=p[i]; 91 check(); 92 for(int j=i;j<=n;++j) 93 if(p[j]==t&&vis[j]) p[j]=s; 94 } 95 printf("%d ",S.size()); 96 return 0; 97 }