题目:洛谷P4126 [AHOI2009]最小割

思路:

结论题

在残余网络上跑tarjan求出所有SCC,记id[u]为点u所在SCC的编号。显然有id[s]!=id[t](否则s到t有通路,能继续增广)。

对于任意一条满流边(u,v),(u,v)能够出现在某个最小割集中,当且仅当id[u]!=id[v];

对于任意一条满流边(u,v),(u,v)必定出现在最小割集中,当且仅当id[u] == id[s]且id[v] == id[t]。

证明:

①将每个SCC缩成一个点,得到的新图就只含有满流边了。那么新图的任一s-t割都对应原图的某个最小割,从中任取一个把id[u]和id[v]割开的割即可证明。

②假设将(u,v)的边权增大,那么残余网络中会出现s->u->v->t的通路,从而能继续增广,于是最大流流量(也就是最小割容量)会增大。这即说明(u,v)是最小割集中必须出现的边。

上述解释已经比较清楚,思维能力有限,还没有想到更好的解释方法,因此不再过多解释。

注意残量网络是指代码中实际建出的图,在跑完最大流之后所有边权大于0的边构成的子图,其中存在反向弧。


Code:

#include <bits/stdc++.h>
using namespace std;
const int N=5e5+5,inf=0x3f3f3f3f;
int n,m,s,t,d[N];
int tim,tp,scc_num,st[N],dfn[N],low[N],belong[N];
int Top=1,ver[N],val[N],nxt[N],head[N];
inline void add(int u,int v,int w){
ver[++Top]=v;val[Top]=w;nxt[Top]=head[u];head[u]=Top;
ver[++Top]=u;val[Top]=0;nxt[Top]=head[v];head[v]=Top;
}
bool bfs(){
for(int i=1;i<=n;++i) d[i]=0;
queue<int> q;
q.push(s);
d[s]=1;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=head[u];i;i=nxt[i]){
int v=ver[i];
if(val[i]&&!d[v]){
d[v]=d[u]+1;
if(v==t) return true;
q.push(v);
}
}
}
return false;
}
int dfs(int u,int flow){
if(u==t) return flow;
int left=flow;
for(int i=head[u];i&&left;i=nxt[i]){
int v=ver[i];
if(val[i]&&d[v]==d[u]+1){
int res=dfs(v,min(left,val[i]));
if(!res) d[v]=0;
val[i]-=res;
val[i^1]+=res;
left-=res;
}
}
return flow-left;
}
void tarjan(int u){
dfn[u]=low[u]=++tim;
st[++tp]=u;
for(int i=head[u];i;i=nxt[i]){
int v=ver[i];
if(!val[i]) continue;//注意此处 在残量网络中tarjan
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(!belong[v]) low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u]){
++scc_num;
int t;
do{
t=st[tp--];
belong[t]=scc_num;
} while(t!=u);
}
}
int main(){
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1,u,v,w;i<=m;++i){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
while(bfs()) dfs(s,inf);
for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
for(int i=2;i<=Top;i+=2){
int u=ver[i^1],v=ver[i];
if(!val[i]&&belong[u]!=belong[v]) printf("%d ",1);
else printf("%d ",0);
if(!val[i]&&belong[u]==belong[s]&&belong[v]==belong[t]) printf("%d",1);
else printf("%d",0);
putchar('\n');
}
return 0;
}

最新文章

  1. ASP.NET Core的配置(4):多样性的配置来源[上篇]
  2. 关于android 5.0对开发带来的影响
  3. JSP简单标签开发
  4. tab切换的两种方法
  5. Java Collection好文章
  6. [OFBiz]开发 五
  7. nginx流量带宽等请求状态统计( ngx_req_status)
  8. zabbix监控redis多实例(low level discovery)
  9. 自定义VIew——漂亮的圆形进度条
  10. 【快速选择算法与nth_element函数】【续UVA11300 】
  11. 【LeetCode练习题】Minimum Window Substring
  12. linux之scp
  13. log4j:ERROR Category option &quot; 1 &quot; not a decimal integer.错误解决
  14. LaTeX 公式编辑
  15. VM Linux版本安装
  16. .Net Core+Angular6 学习 第一部分(创建web api)
  17. Nancyfx框架在传统Webform项目中的应用
  18. Java扫描二维码进行会议签到思路
  19. VS 修改模板文件,增加默认注释
  20. Confluence 6 获得 Active Directory 服务器证书

热门文章

  1. iOS Bezier曲线
  2. springcloud:RPC和HTTP
  3. linux下文件操作之cp和mv
  4. BZOJ 4554: [Tjoi2016&amp;Heoi2016]游戏
  5. 关于CE的反思
  6. Visifire For WPF 图表控件 如何免费
  7. Http中GET和POST请求的区别
  8. 微服务开源生态报告 No.8
  9. Django框架Day3------之Models
  10. vue路由history模式刷新页面出现404问题