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 }

原文地址:https://www.cnblogs.com/bztMinamoto/p/9575318.html

时间: 2024-10-08 20:44:41

bzoj3876: [Ahoi2014&Jsoi2014]支线剧情(上下界费用流)的相关文章

P4043 [AHOI2014/JSOI2014]支线剧情 上下界费用流

题意: 有个人每次可以从1出发(可以无限次)  走有向边  耗费的时间为有向边的长度   问最少耗费的时间遍历所有的边至少一次 有点像滑雪那题  不过那题求得是最少的次数 这题很显然可以转化为上下界费用流  只要设置边的容量为1-inf 即可 注意: 上下界费用流的答案为: 答案即为(求出的费用+原图中边的下界*边的费用) 答案即为(求出的费用+原图中边的下界*边的费用) 答案即为(求出的费用+原图中边的下界*边的费用) 答案即为(求出的费用+原图中边的下界*边的费用) #include<bit

[AHOI2014][bzoj3876] 支线剧情 [上下界费用流]

题面 传送门 思路 转化模型:给一张有向无环图,每次你可以选择一条路径走,花费的时间为路径上边权的总和,问要使所有边都被走至少一遍(可以重复),至少需要花费多久 走至少一遍,等价于覆盖这条边 也就是说,我们要找这个图的一个可重复的路径覆盖 路径覆盖让我们想到什么算法了呢? 网络流啊! 我们考虑建立网络流图模型. 这道题里面有个关键:走过一条边,走几次就要花几次的费用,这想到什么? 费用流嘛! 我们定义走一次路径会给这条路径上的所有边增加1的流量,再给所有边赋一个费用等于边权 这样,我们只要设每条

BZOJ 3876 支线剧情 | 有下界费用流

BZOJ 3876 支线剧情 | 有下界费用流 题意 这题题面搞得我看了半天没看懂--是这样的,原题中的"剧情"指的是边,"剧情点"指的才是点. 题面翻译过来大概是这样: 有一个DAG,每次从1号点出发,走过一条路径,再瞬移回1号点.问:想要遍历所有的边,至少要走多少路程(瞬移回1号点不算路程). 题解 我们用有上下界费用流的模型,建个图: 原图中的每条边,流量范围是\([1, +\infty]\),表示至少走一次,可以走无限次,这条边的费用就是边权. 原图中的每个

bzoj3876 [Ahoi2014&amp;Jsoi2014]支线剧情

3876: [Ahoi2014&Jsoi2014]支线剧情 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2180  Solved: 1300[Submit][Status][Discuss] Description [故事背景] 宅男JYY非常喜欢玩RPG游戏,比如仙剑,轩辕剑等等.不过JYY喜欢的并不是战斗场景,而是类似电视剧一般的充满恩怨情仇的剧情.这些游戏往往 都有很多的支线剧情,现在JYY想花费最少的时间看完所有的支线剧情. [问题描述

【bzoj1927】[Sdoi2010]星际竞速 有上下界费用流

原文地址:http://www.cnblogs.com/GXZlegend/p/6832464.html 题目描述 10年一度的银河系赛车大赛又要开始了.作为全银河最盛大的活动之一,夺得这个项目的冠军无疑是很多人的梦想,来自杰森座α星的悠悠也是其中之一.赛车大赛的赛场由N颗行星和M条双向星际航路构成,其中每颗行星都有一个不同的引力值.大赛要求车手们从一颗与这N颗行星之间没有任何航路的天体出发,访问这N颗行星每颗恰好一次,首先完成这一目标的人获得胜利.由于赛制非常开放,很多人驾驶着千奇百怪的自制赛

【bzoj4108】[Wf2015]Catering 有上下界费用流

原文地址:http://www.cnblogs.com/GXZlegend/p/6832537.html 题目描述 有一家装备出租公司收到了按照时间顺序排列的n个请求. 这家公司有k个搬运工.每个搬运工可以搬着一套装备按时间顺序去满足一些请求.一个搬运工从第i个请求的位置把东西搬到第j个请求的位置需要一些费用.公司的编号是1,请求的编号是2到n+1.所有搬运工必需从公司出发. 求满足所有请求所需的最小搬运费用. 输入 有可能有多组数据.(实际上没有) 第一行两个正整数n,k. 接下来n行,第i行

【bzoj2324】[ZJOI2011]营救皮卡丘 最短路-Floyd+有上下界费用流

原文地址:http://www.cnblogs.com/GXZlegend/p/6832504.html 题目描述 皮卡丘被火箭队用邪恶的计谋抢走了!这三个坏家伙还给小智留下了赤果果的挑衅!为了皮卡丘,也为了正义,小智和他的朋友们义不容辞的踏上了营救皮卡丘的道路. 火箭队一共有N个据点,据点之间存在M条双向道路.据点分别从1到N标号.小智一行K人从真新镇出发,营救被困在N号据点的皮卡丘.为了方便起见,我们将真新镇视为0号据点,一开始K个人都在0号点. 由于火箭队的重重布防,要想摧毁K号据点,必须

hdu 4862 Jump 上下界费用流

对于每个点拆点成为两个点a,b,连接a到b的上界为1,下界为1的边,保证用过一次且仅一次. 然后若点u可到达点v,则连接即可.建成了一个上下界网络,将下界拆出去,求最大费用最大流就好. #include <stdio.h> #include <iostream> #include <string.h> using namespace std; const int N=800; const int MAXE=200000; const int inf=1<<3

Acdream 1171 Matrix sum 上下界费用流

题目链接:点击打开链接 Matrix sum Time Limit: 8000/4000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) SubmitStatisticNext Problem Problem Description sweet和zero在玩矩阵游戏,sweet画了一个N * M的矩阵,矩阵的每个格子有一个整数.zero给出N个数Ki,和M个数Kj,zero要求sweet选出一些数,满足从第 i 行至少选出了Ki