您的位置:首页 > 其它

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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: