【bzoj3876】支线剧情
要求在dag里每条边上界INF下界1费用t。
裸上下界费用流,好像没有什么特定的写法。
首先每条边肯定至少走一次,不妨直接把每条边下界的费用先算上。原来的边正常连容量INF费用t,每个点向1连边表示可以随时返回。由于先计算了下界的费用而忽略下界,所以会导致流量不守恒,考虑普通上下界网络流的写法,新建原点s汇点t,统计每个点下界时流出的流量和流入的流量,此题即出度和入度,令d=入度-出度,若d>0则S向这个点连容量为d费用为0的边,若d<0则向T连容量为-d费用为0的边,跑一遍mcmf加上原来的费用就好了。
#include<bits/stdc++.h> #define maxn 405 #define maxm 100005 #define INF 0x7f7f7f7f using namespace std; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } struct scsc{ int next,from,to,w,c; }edge[maxm<<1]; int Len,head[maxn],ind[maxn],otd[maxn],Sum; void addedge(int u,int v,int w,int c){ edge[++Len].to=v;edge[Len].from=u;edge[Len].w=w;edge[Len].c=c;edge[Len].next=head[u];head[u]=Len; edge[++Len].to=u;edge[Len].from=v;edge[Len].w=0;edge[Len].c=-c;edge[Len].next=head[v];head[v]=Len; } int vis[maxn],d[maxn]; int spfa(int s,int t){ queue<int>Q; for(int i=s;i<=t;++i)vis[i]=0; for(int i=s;i<=t;++i)d[i]=INF; Q.push(s);vis[s]=1;d[s]=0; while(!Q.empty()){ int u=Q.front();Q.pop(); for(int i=head[u];i;i=edge[i].next){ int v=edge[i].to; if(edge[i].w&&d[v]>d[u]+edge[i].c){ d[v]=d[u]+edge[i].c; if(!vis[v]){ vis[v]=1; Q.push(v); } } } vis[u]=0; } return d[t]!=INF; } int ans=0; int dfs(int u,int f,int t){ vis[u]=1; if(u==t)return f; int used=0,w; for(int i=head[u];i&&used<f;i=edge[i].next){ int v=edge[i].to; if(edge[i].w&&d[v]==d[u]+edge[i].c&&!vis[v]){ w=dfs(v,min(f-used,edge[i].w),t); edge[i].w-=w; edge[i^1].w+=w; used+=w; ans+=edge[i].c*w; } } return used; } void mcmf(int s,int t){ while(spfa(s,t)){ vis[t]=1; while(vis[t]){ for(int i=s;i<=t;++i)vis[i]=0; dfs(s,INF,t); } } } int n; int main(){ n=read();int f1,f2; int S=0,T=n+1;Len=1; for(int i=1;i<=n;++i){ otd[i]=read(); for(int j=1;j<=otd[i];++j){ f1=read();f2=read(); ++ind[f1];Sum+=f2; addedge(i,f1,INF,f2); } } for(int i=2;i<=n;++i)addedge(i,1,INF,0); for(int i=2;i<=n;++i){ int du=ind[i]-otd[i]; if(du>0)addedge(S,i,du,0); else addedge(i,T,-du,0); } mcmf(S,T); printf("%d\n",ans+Sum); return 0; }