BZOJ 3876 [AHOI/JSOI2014]支线剧情 (最小费用可行流)
题面:洛谷传送门 BZOJ传送门
题目大意:给你一张有向无环图,边有边权,让我们用任意条从1号点开始的路径覆盖这张图,需要保证覆盖完成后图内所有边都被覆盖至少一次,求覆盖路径总长度的最小值
最小费用可行流板子题..
有源汇最小费用可行流
给定一张有源汇网络流图,必须保证图中每条边的流量都$\in[l,r]$,求最小费用的可行流
我们要想办法把问题转化成最小费用最大流,即每条边流量需求都是$[0,r-l]$的
对于每个点,设$p_{i}$表示$i$点 入边流量下界之和 减掉 出边流量下界之和
根据流量守恒,且我们要求的是最小费用可行流,多余的(去掉后仍然符合要求的)流量要尽可能少
如果$p_{i}>0$,说明当流量尽可能少的时候,流入>流出,修改流量上下界以后,这个点必须要多输入$p_{i}$点流量,才能保证符合流入的下界要求
源点$S$向$i$点连一条流量为$p_{i}$,费用为$0$的边
反之$p_{i}<0$,流出>流入,这个点必须要多输出$p_{i}$点流量,才能保证符合流出的下界要求
$i$点向汇点$T$连一条流量为$p_{i}$,费用为$0$的边
图中的其他边流量都是$[0,r-l]$,费用不变
然后跑最小费用最大流即可
对这道题而言,把$DAG$看成网络流图,那么我们需要保证图中每条边都有流量,即流量的合法范围是$[1,inf]$,按上述方式建图后,跑最小费用最大流即可
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define N1 310 5 #define M1 6010 6 using namespace std; 7 const int inf=0x3f3f3f3f; 8 9 int gint() 10 { 11 int ret=0,fh=1;char c=getchar(); 12 while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();} 13 while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();} 14 return ret*fh; 15 } 16 struct Edge{ 17 int to[M1<<1],nxt[M1<<1],flow[M1<<1],cost[M1<<1],head[N1],cte; 18 void ae(int u,int v,int f,int c) 19 { 20 cte++; to[cte]=v; nxt[cte]=head[u]; 21 head[u]=cte; flow[cte]=f; cost[cte]=c; 22 } 23 }e; 24 25 int dis[N1],use[N1],que[M1*10],flow[N1],id[N1],hd,tl,S,T; 26 int n,K[N1],cnt; 27 int spfa() 28 { 29 int x,j,v; 30 memset(dis,0x3f,(T+1)<<2); memset(flow,0,(T+1)<<2); 31 hd=1,tl=0; que[++tl]=S; dis[S]=0; use[S]=1; flow[S]=inf; 32 while(hd<=tl) 33 { 34 x=que[hd++]; 35 for(j=e.head[x];j;j=e.nxt[j]) 36 { 37 v=e.to[j]; 38 if( dis[v]>dis[x]+e.cost[j] && e.flow[j]>0 ) 39 { 40 dis[v]=dis[x]+e.cost[j]; id[v]=j; 41 flow[v]=min(flow[x],e.flow[j]); 42 if(!use[v]) que[++tl]=v, use[v]=1; 43 } 44 } 45 use[x]=0; 46 } 47 return dis[T]!=inf; 48 } 49 int mxflow=0,tcost=0; 50 void EK() 51 { 52 int x,fl; 53 while(spfa()) 54 { 55 fl=flow[T]; mxflow+=fl; tcost+=fl*dis[T]; 56 for(x=T;x!=S;x=e.to[id[x]^1]) 57 { 58 e.flow[id[x]]-=fl; 59 e.flow[id[x]^1]+=fl; 60 } 61 } 62 } 63 int inc[N1]; 64 65 int main() 66 { 67 scanf("%d",&n); 68 int i,j,x,y,v,ans=0; S=0; T=n+1; e.cte=1; 69 e.ae(S,1,inf,0); e.ae(1,S,0,0); 70 for(i=1;i<=n;i++) 71 { 72 K[i]=gint(); 73 for(j=1;j<=K[i];j++) 74 { 75 x=gint(); y=gint(); 76 inc[i]--; inc[x]++; ans+=y; 77 e.ae(i,x,inf,y); e.ae(x,i,0,-y); 78 } 79 } 80 for(i=1;i<=n;i++) 81 { 82 if(inc[i]>0) e.ae(S,i,inc[i],0), e.ae(i,S,0,0); 83 if(inc[i]<0) e.ae(i,T,-inc[i],0), e.ae(T,i,0,0); 84 } 85 EK(); ans+=tcost; 86 printf("%d\n",ans); 87 return 0; 88 }