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