[ZJOI2011]最小割
无向图任意点对最大流的模板题,把所有元素放进 num
数组里排序 + 二分即可。
Problem
题目描述
小白在图论课上学到了一个新的概念 —— 最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t
的最小割指的是在关于
现给定一张无向图,小白有若干个形如” 图中有多少对点它们的最小割的容量不超过
输入格式
输入文件第一行有且只有一个正整数
对于每组测试数据,第一行包含两个整数
下面
接下来一行,包含一个整数
下面
输出格式
对于每组测试数据,输出应包括
两组测试数据之间用空行隔开。
输入
15 010
输出
10
说明 / 提示
对于
Code
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#define inf 0x3FFFFFFFusing namespace std;struct Node{ int to,next,v;}e[6005],mp[6005];int s,t,n,m,h[155],f[155][155],d[155],gap[155],fa[155],num[22505],cnt=1;bool vis[155];inline void Addedge(int x,int y,int v){ mp[++cnt]=(Node){y,h[x],v};h[x]=cnt;return;}inline int dfs(int x,int maxf){ int i,y,ret=0,delta; if(x==t)return maxf; for(i=h[x];i;i=e[i].next) { y=e[i].to; if(e[i].v&&d[x]==d[y]+1) { delta=dfs(y,min(maxf,e[i].v)); e[i].v-=delta; e[i^1].v+=delta; ret+=delta; maxf-=delta; if(!maxf||d[x]==n)return ret; } } if(!(--gap[d[x]]))d[s]=n; ++gap[++d[x]]; return ret;}inline void dfs(int x){ int i,y; vis[x]=true; for(i=h[x];i;i=e[i].next) { y=e[i].to; if(e[i].v&&!vis[y])dfs(y); } return;}inline void Gusfield(){ int i,j,ans; memset(f,0x3F,sizeof(f)); for(i=2;i<=n;++i)fa[i]=1; for(i=2;i<=n;++i) { memcpy(e,mp,sizeof(mp)); memset(gap,0,sizeof(gap)); memset(d,0,sizeof(d)); memset(vis,0,sizeof(vis)); s=fa[i];t=i;ans=0; gap[0]=n; while(d[s]<n)ans+=dfs(s,inf); dfs(s); for(j=i+1;j<=n;++j) { if(!vis[j]&&fa[j]==fa[i])fa[j]=i; } for(j=1;j<i;++j)f[i][j]=f[j][i]=min(f[fa[i]][j],ans); } return;}int main(void){ int i,j,q,T,x,y,v; scanf("%d",&T); while(T--) { memset(h,0,sizeof(h));cnt=1; scanf("%d%d",&n,&m); for(i=1;i<=m;++i) { scanf("%d%d%d",&x,&y,&v); Addedge(x,y,v); Addedge(y,x,v); } Gusfield();num[0]=0; for(i=1;i<=n;++i) { for(j=i+1;j<=n;++j) { num[++num[0]]=f[i][j]; } } sort(num+1,num+num[0]+1); scanf("%d",&q); for(i=1;i<=q;++i) { scanf("%d",&x); printf("%d\n",upper_bound(num+1,num+num[0]+1,x)-num-1); } putchar('\n'); } return 0;}