bzoj2229: [Zjoi2011]最小割
2017-09-25 10:05
417 查看
听说只有n-1种最小割,于是可以计算一棵最小割树(并不知道怎么证QwQ),不需要真的写出一棵树,只要
不断分治求最小割在ans数组更新答案即可。
不断分治求最小割在ans数组更新答案即可。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; queue<int> q; int read() { char ch=getchar();int f=0; while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9'){f=(f<<1)+(f<<3)+ch-'0';ch=getchar();} return f; } int n,m,tot,s,t,head[155],a[155],sum;bool mark[155]; int dis[155],ans[155][155],tmp[155]; struct node { int from; int to; int next; int w; }edge[100005]; void add(int u,int v,int w) { edge[tot].from=u; edge[tot].to=v; edge[tot].w=w; edge[tot].next=head[u]; head[u]=tot++; } bool bfs() { memset(dis,-1,sizeof(dis)); dis[s]=0; q.push(s); while(!q.empty()) { int x=q.front(); q.pop(); for(int i=head[x];i!=-1;i=edge[i].next) { if(dis[edge[i].to]==-1&&edge[i].w) { dis[edge[i].to]=dis[x]+1; q.push(edge[i].to); } } } if(dis[t]==-1) return 0; return 1; } int dfs(int x,int flow) { if(x==t||!flow) return flow; int ret=0; for(int i=head[x];i!=-1;i=edge[i].next) { if(dis[edge[i].to]==dis[x]+1) { int f=dfs(edge[i].to,min(edge[i].w,flow)); edge[i].w-=f;edge[i^1].w+=f; flow-=f;ret+=f; if(!flow) return ret; } } if(!ret) dis[x]=-1; return ret; } void dinic() { while(bfs()) { sum+=dfs(s,0x7f7f7f7f); } } void dfs(int x) { mark[x]=1; for(int i=head[x];i!=-1;i=edge[i].next) { if(edge[i].w&&!mark[edge[i].to]) { dfs(edge[i].to); } } } void solve(int l,int r) { if(l==r) return; for(int i=0;i<tot;i+=2) { edge[i].w=edge[i^1].w=(edge[i].w+edge[i^1].w)>>1; } s=a[l];t=a[r]; sum=0; dinic(); memset(mark,0,sizeof(mark)); dfs(s); for(int i=1;i<=n;i++) { if(mark[i]) { for(int j=1;j<=n;j++) { if(!mark[j]) { ans[i][j]=ans[j][i]=min(ans[i][j],sum); } } } } int l1=l,r1=r; for(int i=l;i<=r;i++) { if(mark[a[i]]) tmp[l1++]=a[i]; else tmp[r1--]=a[i]; } for(int i=l;i<=r;i++) a[i]=tmp[i]; solve(l,l1-1);solve(r1+1,r); } int main() { int T=read(); while(T--) { n=read();m=read(); memset(head,-1,sizeof(head)); memset(ans,0x7f7f7f7f,sizeof(ans)); tot=0; for(int i=1;i<=n;i++) a[i]=i; for(int i=1;i<=m;i++) { int u=read(),v=read(),w=read(); add(u,v,w); add(v,u,w); } solve(1,n); //cout<<"ok"; int q=read(); while(q--) { int now=read(),cou=0; for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { if(ans[i][j]<=now) cou++; } } printf("%d\n",cou); } puts(""); } }
相关文章推荐
- bzoj千题计划139:bzoj2229: [Zjoi2011]最小割
- BZOJ 2229 ZJOI2011 最小割 最小割+分治 400AC达成&&2000Submission达成
- [ZJOI2011][bzoj2229] 最小割 [最小割树]
- BZOJ 2229: [Zjoi2011]最小割
- Bzoj2229:[Zjoi2011]最小割:分治最小割
- BZOJ2229: [Zjoi2011]最小割 分治最小割
- BZOJ 2521: [Shoi2010]最小生成树&&2229: [Zjoi2011]最小割
- 【BZOJ2229】【ZJOI2011】最小割 {没有错,这道题的算法跟题帽是一样的!!!}
- 【bzoj2229】[Zjoi2011]最小割 分治+网络流最小割
- BZOJ 2229 [Zjoi2011]最小割
- bzoj2229 [Zjoi2011]最小割
- bzoj 2229: [Zjoi2011]最小割 分治&网络流
- BZOJ 2229: [Zjoi2011]最小割 最小割树 / 分治最小割
- bzoj 2229: [Zjoi2011]最小割
- 【BZOJ2229】【ZJOI2011】最小割
- BZOJ 2229 [Zjoi2011] 最小割
- bzoj 2229 [Zjoi2011]最小割(分治+最小割)
- 【bzoj 2229 & luogu 3329】 [ZJOI2011]最小割
- 【ZJOI2011】【BZOJ2229】最小割
- bzoj 2229: [Zjoi2011]最小割【Gomory–Hu tree最小割树】