其他分享
首页 > 其他分享> > BZOJ 3876 [AHOI/JSOI2014]支线剧情 (最小费用可行流)

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 }

 

标签:费用,JSOI2014,AHOI,int,flow,最小,流量,3876,fl
来源: https://www.cnblogs.com/guapisolo/p/10348428.html