bzoj3876: [Ahoi2014&Jsoi2014]支线剧情(上下界费用流)

传送门

 

一道题让我又要学可行流又要学zkw费用流……

考虑一下,原题可以转化为一个有向图,每次走一条路径,把每一条边都至少覆盖一次,求最小代价

因为一条边每走过一次,就要付出一次代价

那不就是费用流了么

我们定义每走一次都会对一条边增加1的流量,1然后费用为时间

那么把下界设为1,上界设为inf,跑一个最小费用可行流就可以了

ps:不会可行流的可以去看看这个博客,我觉得写得很不错->这里

 1 //minamoto
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<queue>
 6 #define inf 0x3f3f3f3f
 7 using namespace std;
 8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 9 char buf[1<<21],*p1=buf,*p2=buf;
10 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
11 inline int read(){
12     #define num ch-'0'
13     char ch;bool flag=0;int res;
14     while(!isdigit(ch=getc()))
15     (ch=='-')&&(flag=true);
16     for(res=num;isdigit(ch=getc());res=res*10+num);
17     (flag)&&(res=-res);
18     #undef num
19     return res;
20 }
21 const int N=505,M=100005;
22 int head[N],Next[M],ver[M],edge[M],flow[M],tot=1;
23 int dis[N],vis[N],S,T,ans;
24 queue<int> q;
25 inline void add(int u,int v,int e,int f){
26     ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e,flow[tot]=f;
27     ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=-e,flow[tot]=0;
28 }
29 bool spfa(){
30     memset(dis,-1,sizeof(dis));
31     memset(vis,0,sizeof(vis));
32     q.push(T),dis[T]=0,vis[T]=1;
33     while(!q.empty()){
34         int u=q.front();q.pop();vis[u]=0;
35         for(int i=head[u];i;i=Next[i])
36         if(flow[i^1]){
37             int v=ver[i],e=edge[i];
38             if(dis[v]<0||dis[v]>dis[u]-e){
39                 dis[v]=dis[u]-e;
40                 if(!vis[v]) vis[v]=1,q.push(v);
41             }
42         }
43     }
44     return ~dis[S];
45 }
46 int dfs(int u,int limit){
47     if(!limit) return 0;
48     if(u==T) return vis[T]=1,limit;
49     int fl=0,f;vis[u]=1;
50     for(int i=head[u];i;i=Next[i]){
51         int v=ver[i];
52         if(dis[v]==dis[u]-edge[i]&&!vis[v]&&(f=dfs(v,min(limit,flow[i])))){
53             fl+=f,limit-=f;
54             ans+=f*edge[i];
55             flow[i]-=f,flow[i^1]+=f;
56             if(!limit) break;
57         }
58     }
59     return fl;
60 }
61 void zkw(){
62     while(spfa()){
63         vis[T]=1;
64         while(vis[T])
65         memset(vis,0,sizeof(vis)),dfs(S,inf);
66     }
67 }
68 int d[N],n;
69 int main(){
70     //freopen("testdata.in","r",stdin);
71     n=read();
72     for(int i=1;i<=n;++i){
73         int t=read();
74         while(t--){
75             int x=read(),y=read();
76             --d[i],++d[x],ans+=y;
77             add(i,x,y,inf);
78         }
79     }
80     S=0,T=n+2;
81     for(int i=2;i<=n;++i) add(i,n+1,0,inf);
82     for(int i=1;i<=n;++i){
83         if(d[i]>0)add(S,i,0,d[i]);
84         if(d[i]<0)add(i,T,0,-d[i]);
85     }
86     add(n+1,1,0,inf);
87     zkw();
88     printf("%d\n",ans);
89     return 0;
90 }

 

posted @ 2018-09-02 21:07  bztMinamoto  阅读(173)  评论(0编辑  收藏  举报
Live2D