[BZOJ4519][CQOI2016]不同的最小割
2018-03-20 23:00
501 查看
bzoj
luogu
我们考虑任选两个点做一个最小割,那么这个最小割就会把原图分成两个点集。设这个最小割的权值为\(val\),那么分处于两个点集的点对之间的最小割一定不大于\(val\)。
然后对于两个点集分别递归处理,每次在当前点集中任意选两个点做最小割,直到点集中只剩下一个点为止。
每次分成两半,显然会做\(n-1\)次。
这个东西叫做最小割树,其实也就是在上述的操作过程中,每次在两个点集之间连权值为最小割权值的边。那么最终就会生成一棵最小割树。
两点之间的最小割就是树上两点间路径的最小值。
但显然并不会用树剖去维护这个最小值,而是会去开一个N^2的数组
这同时也证明了一点:一张图的不同权值的最小割最多只有\(n-1\)个。
所以,求出所有最小割然后去个重就行了。
注意一点:每次跑最小割之前要还原图,也就是平衡每条边与其反向边的流量。直接置为相等就行了。
luogu
sol
每对点对之间跑一遍最小割?naive了吧。我们考虑任选两个点做一个最小割,那么这个最小割就会把原图分成两个点集。设这个最小割的权值为\(val\),那么分处于两个点集的点对之间的最小割一定不大于\(val\)。
然后对于两个点集分别递归处理,每次在当前点集中任意选两个点做最小割,直到点集中只剩下一个点为止。
每次分成两半,显然会做\(n-1\)次。
这个东西叫做最小割树,其实也就是在上述的操作过程中,每次在两个点集之间连权值为最小割权值的边。那么最终就会生成一棵最小割树。
两点之间的最小割就是树上两点间路径的最小值。
但显然并不会用树剖去维护这个最小值,而是会去开一个N^2的数组
这同时也证明了一点:一张图的不同权值的最小割最多只有\(n-1\)个。
所以,求出所有最小割然后去个重就行了。
注意一点:每次跑最小割之前要还原图,也就是平衡每条边与其反向边的流量。直接置为相等就行了。
code
#include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; int gi() { int x=0,w=1;char ch=getchar(); while ((ch<'0'||ch>'9')&&ch!='0') ch=getchar(); if (ch=='-') w=0,ch=getchar(); while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return w?x:-x; } const int N = 900; const int inf = 1e9; struct edge{int to,nxt,w;}a[N<<5]; int n,m,head ,cnt=1,dep ,cur ,q ,tmp ,o ,len; queue<int>Q; void link(int u,int v,int w) { a[++cnt]=(edge){v,head[u],w}; head[u]=cnt; a[++cnt]=(edge){u,head[v],w}; head[v]=cnt; } bool bfs(int s,int t) { memset(dep,0,sizeof(dep)); dep[s]=1;Q.push(s); while (!Q.empty()) { int u=Q.front();Q.pop(); for (int e=head[u];e;e=a[e].nxt) if (a[e].w&&!dep[a[e].to]) dep[a[e].to]=dep[u]+1,Q.push(a[e].to); } return dep[t]; } int dfs(int u,int f,int t) { if (u==t) return f; for (int &e=cur[u];e;e=a[e].nxt) if (a[e].w&&dep[a[e].to]==dep[u]+1) { int tmp=dfs(a[e].to,min(a[e].w,f),t); if (tmp) {a[e].w-=tmp;a[e^1].w+=tmp;return tmp;} } return 0; } int Dinic(int s,int t) { int res=0; while (bfs(s,t)) { for (int i=1;i<=n;++i) cur[i]=head[i]; while (int tmp=dfs(s,inf,t)) res+=tmp; } return res; } void solve(int L,int R) { if (L==R) return; for (int i=3;i<=cnt;++i) a[i].w=a[i^1].w=(a[i].w+a[i^1].w)>>1; o[++len]=Dinic(q[L],q[R]); int l=L-1,r=R+1; for (int i=L;i<=R;++i) if (dep[q[i]]) tmp[++l]=q[i]; else tmp[--r]=q[i]; for (int i=L;i<=R;++i) q[i]=tmp[i]; solve(L,l);solve(r,R); } int main() { n=gi();m=gi(); for (int i=1;i<=m;++i) { int u=gi(),v=gi(),w=gi(); link(u,v,w); } for (int i=1;i<=n;++i) q[i]=i; solve(1,n); sort(o+1,o+len+1);len=unique(o+1,o+len+1)-o-1; printf("%d\n",len);return 0; }
相关文章推荐
- bzoj4519 [Cqoi2016]不同的最小割
- bzoj 4519: [Cqoi2016]不同的最小割 最小割树
- bzoj 4519 [Cqoi2016]不同的最小割
- BZOJ 4519 [Cqoi2016]不同的最小割 最小割树(分治最小割)
- bzoj4519 [Cqoi2016]不同的最小割 分治最小割 模板
- 【BZOJ4519】[Cqoi2016]不同的最小割 最小割树
- bzoj 4519: [Cqoi2016]不同的最小割 分治&最小割
- bzoj4519【CQOI2016】不同的最小割
- BZOJ 4519: [Cqoi2016]不同的最小割 最小割树 / 分治最小割
- 【bzoj4519】[Cqoi2016]不同的最小割 分治+最小割
- [分治最小割] BZOJ 4519 [Cqoi2016]不同的最小割
- BZOJ4519: [Cqoi2016]不同的最小割
- BZOJ 4519: [Cqoi2016]不同的最小割
- bzoj 4519: [Cqoi2016]不同的最小割
- bzoj4519: [Cqoi2016]不同的最小割
- bzoj4519 [Cqoi2016]不同的最小割(最小割树,分治)
- BZOJ 4519 [CQOI2016]不同的最小割
- bzoj千题计划140:bzoj4519: [Cqoi2016]不同的最小割
- bzoj 4519: [Cqoi2016]不同的最小割【最小割树Gomory–Hu tree】
- bzoj 4519: [Cqoi2016]不同的最小割 最小割树