习题:codevs 1035 火车停留解题报告

本蒟蒻又来写解题报告了。这次的题目是codevs 1035 火车停留。

题目大意就是给m个火车的到达时间、停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润,让你来求一种安排方法,使得车站收益最大,并输出收益值。

蒟蒻的思路是这样的:

一眼看出:最大费用最大流(MCMF)
显然cost:表示车站收益
然后……
以车站为点建立图求流?同一个车站可能经过好几辆火车……,貌似很麻烦……;
那么以什么建图、连边,还有怎么连?
貌似有点类似于方格取数2之中的拆点……;
那么这个就可以……以火车为点,把一个点拆成两个,然后建立流的关系。
Reach[i]和stay[i]作为建立不同火车是否可以建边的判断条件
假设火车i,将其分为点2*i-1和2*i,连一条流量为1,费用为-cost[i]的边
如果reach[i] + stay[i] < reach[j],在2*i和2*j-1之间连一条流量为1,费用为0的边。
建立汇点和起点S,T,从S向每个2*i-1连一条流量为1,费用为0的边。从每个2*i向T连一条流量为1,费用为0的边。

那么怎么限制n个车道呢?其实很简单,只需要建立超级汇点ST,然后从T向ST连一条流量为n,费用为0的边。

这样这个题目就大功告成了,代码不长,刚98行。建议大家还是去刷一下代码能力题,因为NOIP2015蒟蒻就被代码能力题给坑惨了。

废话不多说,上代码

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <queue>
 7 using namespace std;
 8 const int INF = 10000000;
 9 const int maxe = 10000;
10 const int maxn = 500;
11 int n,m,reach[maxn],stay[maxn],cost[maxn],vis[maxn<<1],d[maxn<<1],h[maxn<<1],pre[maxn<<1],rid[maxn],cid[maxn],now;
12 double ans;
13 struct edge{
14     int to,cost,cap,next;
15 }tr[maxe];
16 inline void init(){
17     now = 0;
18     memset(h,-1,sizeof(h));
19     memset(tr,0,sizeof(tr));
20     memset(reach,0,sizeof(reach));
21     memset(stay,0,sizeof(stay));
22     memset(cost,0,sizeof(cost));
23 }
24 inline void add(int u,int v,int cap,int cost){
25     tr[now].to = v;tr[now].cap = cap;tr[now].cost = cost;tr[now].next = h[u];
26     h[u] = now++;
27     tr[now].to = u;tr[now].cap = 0;tr[now].cost = -cost;tr[now].next = h[v];
28     h[v] = now++;
29 }
30 bool SPFA(int s,int t,int &flow,int &cost){
31     for(int i = s;i <= t;++i){
32         d[i] = INF;
33     }
34     int minflow = INF;
35     memset(vis,0,sizeof(vis));
36     memset(pre,-1,sizeof(pre));
37     deque<int>q;
38     d[s] = 0;
39     vis[s] = 1;
40     q.push_back(s);
41     while(!q.empty()){
42         int x = q.front();q.pop_front();
43         vis[x] = 0;
44         for(int i = h[x];i != -1;i = tr[i].next){
45             edge e = tr[i];
46             if(d[e.to] > d[x] + e.cost && e.cap){
47                 d[e.to] = d[x] + e.cost;
48                 pre[e.to] = i;
49                 minflow = min(minflow,e.cap);
50                 if(!vis[e.to]){
51                     vis[e.to] = 1;
52                     q.push_back(e.to);
53                 }
54             }
55         }
56     }
57     if(d[t] == INF)return false;
58     flow += minflow;
59     cost += d[t] * minflow;
60     for(int i = t;i != s;i = tr[pre[i]^1].to){
61         tr[pre[i]].cap -= minflow;
62         tr[pre[i]^1].cap += minflow;
63     }
64     return true;
65 }
66 int MCMF(int s,int t){
67     int flow = 0,cost = 0;
68     while(SPFA(s,t,flow,cost));
69     return cost;
70 }
71 int main(){
72     scanf("%d%d",&n,&m);
73     init();
74     for(int i = 1;i <= m;++i){
75         scanf("%d%d%d",&reach[i],&cost[i],&stay[i]);
76         rid[i] = 2*i;cid[i] = 2*i-1;
77         add(cid[i],rid[i],1,-cost[i]);
78     }
79     for(int i = 1;i <= m;++i){
80         for(int j = 1;j <= m;++j){
81             if(j != i)
82                 if(reach[i] + stay[i] < reach[j]){
83                     add(rid[i],cid[j],1,0);
84                 }
85         }
86     }
87     int S = 0,T = 2*m+1,ST = 2*m+2;
88     for(int i = 1;i <= m;++i){
89         add(S,cid[i],1,0);
90     }
91     for(int i = 1;i <= m;++i){
92         add(rid[i],T,1,0);
93     }
94     add(T,ST,n,0);
95     ans = double(MCMF(S,ST))/100;
96     printf("%0.2lf\n",-ans);
97     return 0;
98 }

如果大家认为有用的话,欢迎转载。如果大家有意见的话,请在下方评论栏中给我留言,或者给我的E-mail [email protected]发邮件留言。谢谢大家。

时间: 2024-10-10 15:25:18

习题:codevs 1035 火车停留解题报告的相关文章

1035 火车停留 最大费用最大流

1035 火车停留 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 查看运行结果 题目描述 Description "今天你要去远行,送你风雨中-..",伴着凄美的歌声,郭靖夫妇终于踏上征程.为了尽快到达边疆为国效力,他们搭上了2002次列车.可在途径sweet station时,被该站站长缠住了身,是什么原因呢?  因为该车站由于经营不善,面临破产,该站负责人早闻黄蓉聪明过人,一定要她帮忙出出主意,挽救车站.  该车站有n个车道,由于车道的

Code 1035 火车停留 【最大费用最大流】

题目:Code 1035 火车停留 题目:中文题目,直接读吧 分析:读题之后发现是让费用最大,不easy考虑到费用流,事实上费用最大和最小是一样的,费用最大的话能够把费用变为负值求最小的. 建图方法: 超级源点 ss 连接 s ,容量为 n ,费用为0 把每一个列车拆成两个点 i 和 ii .之间建边容量为1 .费用为给车站交的钱的相反数 s 连接 i ,容量inf ,费用0 ii 连接 t ,容量inf ,费用0 全部时刻末点在初点前面的,枚举建边.容量为1,费用0 然后求一次费用流.其相反数

习题:codevs 2822 爱在心中 解题报告

这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页). 这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联通分量里面只有这一道题. 题目是这样的: “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动.爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home.” 在爱的国度里有N个人,在他们的心中都有着一个爱的名单,上面记载着他所爱的人(不会出现自爱的情况).爱是

习题: codevs 2492 上帝造题的七分钟2 解题报告

这道题是受到大犇MagHSK的启发我才得以想出来的,蒟蒻觉得自己的代码跟MagHSK大犇的代码完全比不上,所以这里蒟蒻就套用了MagHSK大犇的代码(大家可以关注下我的博客,友情链接就是大犇MagHSK的博客,大神是山东省队队员,他的博客中的题的质量都比我高几个档次): 这是大神MagHSK的解释:因为10^9顶多开5~6次方就成了1了(当然这里的等于是向下取整的)因此对于修改操作,如果某一段不是1或不是0,就暴力修改,如果是1/0就不管他.修改完之后update一下就好了. 题目上说我们给出的

Codevs 1503 愚蠢的宠物 解题报告

Codevs 1503 愚蠢的宠物 解题报告 题目描述 Description 大家都知道,sheep有两只可爱的宠物(一只叫神牛,一只叫神菜).有一天,sheep带着两只宠物到狗狗家时,这两只可爱的宠物竟然迷路了-- 狗狗的家因为常常遭到猫猫的攻击,所以不得不把家里前院的路修得非常复杂.狗狗家前院有N个连通的分叉结点,且只有N-1条路连接这N个节点,节点的编号是1-N(1为根节点).sheep的宠物非常笨,他们只会向前走,不会退后(只向双亲节点走),sheep想知道他们最早什么时候会相遇(即步

CodeVS第四次月赛解题报告

1.   奶牛的身高 题目描述 Description 奶牛们在FJ的养育下茁壮成长.这天,FJ给了奶牛Bessie一个任务,去看看每个奶牛场中若干只奶牛的身高,由于Bessie是只奶牛,无法直接看出第i只奶牛的身高,而只能看出第i只奶牛与第j只奶牛的身高差,其中第i只奶牛与第j只奶牛的身高差为Ai(i<=n).当A大于0时表示这只奶牛比前一只奶牛高A cm,小于0时则是低.现在,FJ让Bessie总共去看了m次身高,当然也就传回给FJ m对奶牛的身高差,但是Bessie毕竟是奶牛,有时候眼睛可

解题报告——-2018级2016第二学期第三周作业

解题报告——2018级2016第二学期第三周作业 A:[NOIP2002P]过河卒 题目: 描述 如图,A 点有一个过河卒,需要走到目标 B   点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点.例 如上图 C  点上的马可以控制 9 个点(图中的P1,P2 … P8 和 C).卒不能通过对方马的控制点. 棋盘用坐标表示,A 点(0,0).B 点(n,m)(n,m 为不超过 20  的整数,并由键盘输入)

NOIp 2013 Day1 解题报告

NOIp 2013 Day1 解题报告 1.   转圈游戏 不难看出答案就是(x+m*10k) mod n 用快速幂算法,复杂度O(log2k) 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 8 //variable// 9 int n,m,x,

【解题报告】Tempter of the Bone(DFS)

解题报告——Tempter of the Bon 问题描述 Time Limit: 1000ms Memory Limit: 32768KB 64-bit integer IO format: %I64d      Java class name: Main The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to