[bzoj4519][Cqoi2016]不同的最小割_网络流_最小割_最小割树
不同的最小割 bzoj-4519 Cqoi-2016
题目大意:题目链接。
注释:略。
想法:
我们发现这和最小割那题比较像。
我们依然通过那个题说的办法一样,构建最小割树即可。
接下来就是随便怎么处理都行了。
我们可以弄一个数组把枚举到的距离都记录下来即可。
Code:
#include <bits/stdc++.h> #define N 860 #define M 17010 using namespace std; queue<int> q; int n,head[N],to[M],val[M],next[M],tot=1,s,t,dis[N],a[N],tmp[N],ans[N][N],v[1000000],tot; inline void add(int x,int y,int z) { to[++tot]=y,val[tot]=z,next[tot]=head[x],head[x]=tot; to[++tot]=x,val[tot]=z,next[tot]=head[y],head[y]=tot; } bool bfs() { int x,i; memset(dis,0,sizeof(dis)); while(!q.empty()) q.pop(); dis[s]=1,q.push(s); while(!q.empty()) { x=q.front(),q.pop(); for(i=head[x];i;i=next[i]) { if(val[i]&&!dis[to[i]]) { dis[to[i]]=dis[x]+1; if(to[i]==t) return 1; q.push(to[i]); } } } return 0; } int dinic(int x,int low) { if(x==t) return low; int temp=low,i,k; for(i=head[x];i;i=next[i]) { if(val[i]&&dis[to[i]]==dis[x]+1) { k=dinic(to[i],min(temp,val[i])); if(!k) dis[to[i]]=0; val[i]-=k,val[i^1]+=k; if(!(temp-=k)) break; } } return low-temp; } void solve(int l,int r) { if(l >= r) return; int i,j,sum=0,p1,p2; for(i=2;i <= tot;i+=2) val[i]=val[i^1]=(val[i]+val[i^1]) >> 1; s=a[l],t=a[r]; while(bfs()) sum+=dinic(s,1<<30); for(i=1;i <= n;i++) if(dis[i]) for(j=1;j <= n;j++) if(!dis[j]) ans[i][j]=ans[j][i]=min(ans[i][j],sum); for(p1=i=l,p2=r;i <= r;i++) { if(dis[a[i]]) tmp[p1++]=a[i]; else tmp[p2--]=a[i]; } for(i=l;i <= r;i++) a[i]=tmp[i]; solve(l,p2),solve(p1,r); } int main() { int m,i,j,x,y,z,ret=0; scanf("%d%d",&n,&m); while(m--) scanf("%d%d%d",&x,&y,&z),add(x,y,z); for(i=1;i <= n;i++) a[i]=i; memset(ans,0x7f,sizeof(ans)),solve(1,n); for(i=1;i <= n;i++) for(j=i+1;j <= n;j++) v[++tot]=ans[i][j]; sort(v+1,v+tot+1); v[0]=-1<<30; for(i=1;i <= tot;i++) if(v[i] != v[i-1]) ret++; printf("%d\n",ret); return 0; }
小结:最小割树的应用我就碰见了这么两道题。
| 欢迎来原网站坐坐! >原文链接<