网络流(3)——最小割树
来源:互联网 发布:淘宝针织衫 编辑:程序博客网 时间:2024/05/29 08:53
啊,学渣苦,学渣累
什么是最小割树
emm…
可以通过不需要做
怎么做
分治。
首先我们随机选
然后原图就被分为了与
然后分治
据说能证明,然而并不会。
其实连带更新是
局部代码长这样
void mergesort(int l,int r){ if(l==r) return ; for(int i=2;i<=tot;i+=2) wide[i]=wide[i^1]=(wide[i]+wide[i^1])>>1; S=id[l];T=id[r]; tmpflow=solve(); memset(vis,false,sizeof(vis)); dfs(S); for(int i=1;i<=n;++i) if(vis[i]) for(int j=1;j<=n;++j) if(!vis[j]) flowsze[i][j]=flowsze[j][i]=min(tmpflow,flowsze[i][j]); int lef=l,righ=r; for(int i=l;i<=r;++i) if(vis[id[i]]) tmp[lef++]=id[i]; else tmp[righ--]=id[i]; for(int i=l;i<=r;++i) id[i]=tmp[i]; if(lef!=l) mergesort(l,lef-1); if(righ!=r) mergesort(righ+1,r);}
习题
(1)最小割(ZJOI2011)
——“有限次数询问,求有多少点对的最小割小于给定值”
——“这不是裸题么”
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<ctime>#include<cmath>#include<algorithm>#include<cctype>#include<iomanip>#include<queue>using namespace std;inline int read(){ int i=0,f=1; char ch; for(ch=getchar();!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) i=(i<<3)+(i<<1)+(ch^48); return i*f;}int buf[1024];inline void write(int x){ if(!x){putchar('0');return ;} if(x<0){putchar('-');x=-x;} while(x){buf[++buf[0]]=x%10,x/=10;} while(buf[0]) putchar(buf[buf[0]--]+48); return ;}#define stan 222#define sten 7777int tot,first[stan],nxt[sten],goal[sten],wide[sten];int tmp[stan],id[stan],flowsze[stan][stan],ans,n,m,q,tmpflow,a,b,c;int S,T,level[stan];bool vis[stan];queue<int>que;void addedge(int a,int b,int c){ nxt[++tot]=first[a];first[a]=tot;goal[tot]=b;wide[tot]=c; nxt[++tot]=first[b];first[b]=tot;goal[tot]=a;wide[tot]=c; return ;}bool bfs(){ while(!que.empty()) que.pop(); for(int i=1;i<=n;++i) level[i]=-1; level[S]=0;que.push(S); while(!que.empty()){ int u=que.front();que.pop(); for(int p=first[u];p;p=nxt[p]) if(wide[p]&&level[goal[p]]==-1){ level[goal[p]]=level[u]+1; if(goal[p]==T) return true; que.push(goal[p]); } } return false;}int dfs(int u,int flow){ if(u==T) return flow; int ret=0,data; for(int p=first[u];p;p=nxt[p]) if(wide[p]&&level[goal[p]]==level[u]+1){ data=dfs(goal[p],min(flow-ret,wide[p])); if(data){ wide[p]-=data; wide[p^1]+=data; ret+=data; if(ret==flow) return ret; } } level[u]=-1; return ret;}int solve(){ int ret=0; while(bfs()) ret+=dfs(S,999999999); return ret;}void dfs(int u){ vis[u]=true; for(int p=first[u];p;p=nxt[p]) if(wide[p]&&vis[goal[p]]==false) dfs(goal[p]); return ;}void mergesort(int l,int r){ if(l==r) return ; for(int i=2;i<=tot;i+=2) wide[i]=wide[i^1]=(wide[i]+wide[i^1])>>1; S=id[l];T=id[r]; tmpflow=solve(); memset(vis,false,sizeof(vis)); dfs(S); for(int i=1;i<=n;++i) if(vis[i]) for(int j=1;j<=n;++j) if(!vis[j]) flowsze[i][j]=flowsze[j][i]=min(tmpflow,flowsze[i][j]); int lef=l,righ=r; for(int i=l;i<=r;++i) if(vis[id[i]]) tmp[lef++]=id[i]; else tmp[righ--]=id[i]; for(int i=l;i<=r;++i) id[i]=tmp[i]; if(lef!=l) mergesort(l,lef-1); if(righ!=r) mergesort(righ+1,r); return ;}signed main(){ int t=read(); while(t--){ n=read();m=read();tot=1; memset(first,0,sizeof(first)); memset(flowsze,127,sizeof(flowsze)); for(int i=1;i<=n;++i) id[i]=i; for(int i=1;i<=m;++i){ a=read();b=read();c=read(); addedge(a,b,c); } mergesort(1,n); q=read(); for(int i=1;i<=q;++i){ tmpflow=read();ans=0; for(int j=1;j<n;++j) for(int k=j+1;k<=n;++k) if(flowsze[j][k]<=tmpflow) ++ans; write(ans);puts(""); } puts(""); } return 0;}
(2)不同的最小割(cqoi2016)
求有多少种数值不同的最小割
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<ctime>#include<cmath>#include<algorithm>#include<cctype>#include<iomanip>#include<queue>using namespace std;inline int read(){ int i=0,f=1; char ch; for(ch=getchar();!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) i=(i<<3)+(i<<1)+(ch^48); return i*f;}int buf[1024];inline void write(int x){ if(!x){putchar('0');return ;} if(x<0){putchar('-');x=-x;} while(x){buf[++buf[0]]=x%10,x/=10;} while(buf[0]) putchar(buf[buf[0]--]+48); return ;}#define stan 1111#define sten 22222int tot,first[stan],nxt[sten],goal[sten],wide[sten];int tmp[stan],id[stan],flowsze[stan][stan],ans,n,m,q,tmpflow,a,b,c;int S,T,level[stan],line[stan*stan],cnt;bool vis[stan];queue<int>que;void addedge(int a,int b,int c){ nxt[++tot]=first[a];first[a]=tot;goal[tot]=b;wide[tot]=c; nxt[++tot]=first[b];first[b]=tot;goal[tot]=a;wide[tot]=c; return ;}bool bfs(){ while(!que.empty()) que.pop(); for(int i=1;i<=n;++i) level[i]=-1; level[S]=0;que.push(S); while(!que.empty()){ int u=que.front();que.pop(); for(int p=first[u];p;p=nxt[p]) if(wide[p]&&level[goal[p]]==-1){ level[goal[p]]=level[u]+1; if(goal[p]==T) return true; que.push(goal[p]); } } return false;}int dfs(int u,int flow){ if(u==T) return flow; int ret=0,data; for(int p=first[u];p;p=nxt[p]) if(wide[p]&&level[goal[p]]==level[u]+1){ data=dfs(goal[p],min(flow-ret,wide[p])); if(data){ wide[p]-=data; wide[p^1]+=data; ret+=data; if(ret==flow) return ret; } } level[u]=-1; return ret;}int solve(){ int ret=0; while(bfs()) ret+=dfs(S,999999999); return ret;}void dfs(int u){ vis[u]=true; for(int p=first[u];p;p=nxt[p]) if(wide[p]&&vis[goal[p]]==false) dfs(goal[p]); return ;}void mergesort(int l,int r){ if(l==r) return ; for(int i=2;i<=tot;i+=2) wide[i]=wide[i^1]=(wide[i]+wide[i^1])>>1; S=id[l];T=id[r]; tmpflow=solve(); memset(vis,false,sizeof(vis)); dfs(S); for(int i=1;i<=n;++i) if(vis[i]) for(int j=1;j<=n;++j) if(!vis[j]) flowsze[i][j]=flowsze[j][i]=min(tmpflow,flowsze[i][j]); int lef=l,righ=r; for(int i=l;i<=r;++i) if(vis[id[i]]) tmp[lef++]=id[i]; else tmp[righ--]=id[i]; for(int i=l;i<=r;++i) id[i]=tmp[i]; if(lef!=l) mergesort(l,lef-1); if(righ!=r) mergesort(righ+1,r);}signed main(){ n=read();m=read();tot=1; memset(flowsze,127,sizeof(flowsze)); for(int i=1;i<=n;++i) id[i]=i; for(int i=1;i<=m;++i){ a=read();b=read();c=read(); addedge(a,b,c); } mergesort(1,n); for(int i=1;i<n;++i) for(int j=i+1;j<=n;++j) line[++cnt]=flowsze[i][j]; sort(line+1,line+cnt+1); for(int i=1;i<=cnt;++i) if(line[i]!=line[i-1]) ++ans; write(ans); return 0;}
(3)juice junction(bzoj4435)
求
你需要蛤希优化一下
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<ctime>#include<cmath>#include<algorithm>#include<cctype>#include<iomanip>#include<queue>using namespace std;inline int read(){ int i=0,f=1; char ch; for(ch=getchar();!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) i=(i<<3)+(i<<1)+(ch^48); return i*f;}int buf[1024];inline void write(int x){ if(!x){putchar('0');return ;} if(x<0){putchar('-');x=-x;} while(x){buf[++buf[0]]=x%10,x/=10;} while(buf[0]) putchar(buf[buf[0]--]+48); return ;}#define stan 3333#define sten 11111int tot,first[stan],nxt[sten],goal[sten],wide[sten];int tmp[stan],id[stan],ans,n,m,q,tmpflow,a,b,c,pre[stan],edg[stan];int S,T,level[stan],ret;unsigned long long hash[4][stan],base;bool vis[stan];queue<int>que;void addedge(int a,int b,int c){ nxt[++tot]=first[a];first[a]=tot;goal[tot]=b;wide[tot]=c; nxt[++tot]=first[b];first[b]=tot;goal[tot]=a;wide[tot]=c; return ;}bool bfs(){ while(!que.empty()) que.pop(); for(int i=1;i<=n;++i) level[i]=-1; level[S]=0;que.push(S); while(!que.empty()&&level[T]==-1){ int u=que.front();que.pop(); for(int p=first[u];p;p=nxt[p]) if(wide[p]&&level[goal[p]]==-1){ level[goal[p]]=level[u]+1; pre[goal[p]]=u; edg[goal[p]]=p; if(goal[p]==T) break; que.push(goal[p]); } } if(level[T]!=-1){ ++ret; for(int u=T;u!=S;u=pre[u]){ --wide[edg[u]]; ++wide[edg[u]^1]; } } return level[T]!=-1;}int solve(){ ret=0; while(bfs()); return ret;}inline void dfs(int u){ vis[u]=true; for(int p=first[u];p;p=nxt[p]) if(wide[p]&&vis[goal[p]]==false) dfs(goal[p]); return ;}void mergesort(int l,int r){ if(l==r) return ; for(int i=2;i<=tot;i+=2) wide[i]=wide[i^1]=(wide[i]+wide[i^1])>>1; S=id[l];T=id[r]; tmpflow=solve(); memset(vis,false,sizeof(vis)); dfs(S); base*=131; for(int i=1;i<=n;++i) if(~level[i]) hash[tmpflow][i]+=base; int lef=l,righ=r; for(int i=l;i<=r;++i) if(vis[id[i]]) tmp[lef++]=id[i]; else tmp[righ--]=id[i]; for(int i=l;i<=r;++i) id[i]=tmp[i]; if(lef!=l) mergesort(l,lef-1); if(righ!=r) mergesort(righ+1,r); return ;}signed main(){ n=read();m=read();tot=1;base=1; for(int i=1;i<=n;++i) id[i]=i; for(int i=1;i<=m;++i){ a=read();b=read(); addedge(a,b,1); } mergesort(1,n); for(int i=1;i<n;++i) for(int j=i+1;j<=n;++j) for(int k=0;k<=3;++k) if(hash[k][i]!=hash[k][j]){ ans+=k; break; } write(ans); return 0;}
阅读全文
0 0
- 网络流(3)——最小割树
- 网络流 最小割
- 网络流 最小割
- 网络流(1)——最大流、最小割
- 网络流一般建模方式——最小割篇
- 最大流—最小割
- BZOJ 2561 最小生成树 网络流 最小割
- Bzoj2561:最小生成树:网络流,最小割
- hdu1569网络流最小割
- vijosP1524网络流最小割
- 网络流——最大流打二分图、最小割
- 网络流 最大流—最小割 之SAP算法 详解
- 网络流(2)——最小割、最大权闭合图
- 网络流最大流最小割算法
- 网络流最大流最小割算法
- 网络流 最小割最大流定理
- HDU3491 网络流最小割模型
- poj 3469 网络流最小割
- String 类型不可变 如何理解?
- Material Design之侧滑
- 给UITabbar 添加 红色badge数字提醒和红点提醒
- [随便扯几句] 关于数据结构
- sql 两时间做差取出来天时分秒
- 网络流(3)——最小割树
- 两道很有意思的题目POJ 2996,POJ2993
- LuoguP3927 SAC E#1
- Y720安装windows10和ubuntu双系统
- Myeclipse导入包时的快捷键
- 巨佬们的博客(没事可以去学习学习)
- 平时整理的一些命令等
- EA&UML日拱一卒-状态图::庖丁解牛
- C++实现顺序栈