FJ省队集训DAY3 T2
2016-07-05 21:19
267 查看
思路:如果一个DAG要的路径上只要一条边去切掉,那么要怎么求?很容易就想到最小割,但是如果直接做最小割会走出重复的部分,那我们就这样:反向边设为inf,这样最小割的时候就不会割到了,判断无解我们直接用tarjan
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #include<algorithm> #define ll long long const ll inf = 1ll << 60; struct edge{ int u,v,w; }e[200005]; ll flow[200005]; int op[200005],dis[200005],cnt[200005],a[115][115],pd[10005]; int tot,go[200005],next[200005],first[200005],S,T,nodes,sz; int n,m,vis[200005],instack[200005],c[200005],top,dfn[200005],low[200005],belong[200005],num; int read(){ int t=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();} while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} return t*f; } void insert(int x,int y){ tot++; go[tot]=y; next[tot]=first[x]; first[x]=tot; } void insert(int x,int y,ll z){ tot++; go[tot]=y; next[tot]=first[x]; first[x]=tot; flow[tot]=z; } void add(int x,int y,ll z){ insert(x,y,z);op[tot]=tot-1; insert(y,x,inf);op[tot]=tot+1; } void tarjan(int x){ vis[x]=instack[x]=1; c[++top]=x;dfn[x]=low[x]=++sz; for (int i=first[x];i;i=next[i]){ int pur=go[i]; if (!vis[pur]){ tarjan(pur); low[x]=std::min(low[x],low[pur]); }else if (instack[pur]){ low[x]=std::min(low[x],dfn[pur]); } } if (low[x]==dfn[x]){ num++; while (c[top]!=x){ belong[c[top]]=num; instack[c[top]]=0; top--; } belong[c[top]]=num; instack[c[top]]=0; top--; } } ll dfs(int x,ll f){ if (x==T) return f; int mn=nodes;ll sum=0; for (int i=first[x];i;i=next[i]){ int pur=go[i]; if (flow[i]&&dis[pur]+1==dis[x]){ ll F=std::min(f-sum,flow[i]); ll save=dfs(pur,F); flow[i]-=save; flow[op[i]]+=save; sum+=save; if (dis[S]>=nodes||f==sum) return sum; } if (flow[i]) mn=std::min(mn,dis[pur]); } if (sum==0){ cnt[dis[x]]--; if (cnt[dis[x]]==0){ dis[S]=nodes; }else{ dis[x]=mn+1; cnt[dis[x]]++; } } return sum; } int main(){ n=read();m=read(); for (int i=1;i<=m;i++){ e[i].u=read()+1,e[i].v=read()+1,e[i].w=read(); a[e[i].u][e[i].v]=1; insert(e[i].u,e[i].v); } for (int i=1;i<=n;i++) if (!vis[i]) tarjan(i); if (belong[1]==belong ){ puts("-1"); return 0; } for (int i=1;i<=n;i++) a[i][i]=1; for (int k=1;k<=n;k++) for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) a[i][j]|=a[i][k]&&a[k][j]; for (int i=1;i<=n;i++) if (a[1][i]&&a[i] ) pd[i]=1; for (int i=1;i<=m;i++) if (pd[e[i].u]&&pd[e[i].v]) add(e[i].u,e[i].v,e[i].w); S=1;T=n;nodes=n; int ans=0; while (dis[S]<nodes&&ans<inf) ans+=dfs(S,inf); if (ans==0) printf("-1"); else printf("%d\n",ans); }
相关文章推荐
- 关于View和viewGroup的绘制方法mearsure(),layout(),draw()
- Android设计模式之观察者模式 Observer
- win10安装VS2015专业版无法新项目问题
- Android设计模式之观察者模式 Observer
- Android设计模式之观察者模式 Observer
- Android设计模式之观察者模式 Observer
- java多线程系列02
- CreateProcess创建的子进程的命令行参数
- SQL 2016 安装
- poj 1995 快速幂【裸】
- 请叫我程序员 第9章
- VC编程经验汇总(二)
- 【分享】传颂之物1+2虚伪的面具 序章【汉化硬盘版】[全CG存档&攻略+英化补丁]
- 嵌套矩形问题
- C++的iostream标准库介绍
- 华为机试题--3.明明的随机数
- Python3 Pickle报错 TypeError
- Objective-C中的@property
- 【iOS】设置 rootViewController
- “爱运动管理系统”诞生记(10)