[SDOI2009] 晨跑 (费用流) ---链表 VS Vector

Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑、仰卧起坐等等,不过到目前为止,他坚持下来的只有晨跑。
现在给出一张学校附近的地图,这张地图中包含N个十字路口和M条街道,Elaxia只能从一个十字路口跑向另外一个十字路口,街道之间只在十字路口处相交。Elaxia每天从寝室出发跑到学校,保证寝室编号为1,学校编号为N。
Elaxia的晨跑计划是按周期(包含若干天)进行的,由于他不喜欢走重复的路线,所以在一个周期内,每天的晨跑路线都不会相交(在十字路口处),寝室和学校不算十字路口。Elaxia耐力不太好,他希望在一个周期内跑的路程尽量短,但是又希望训练周期包含的天数尽量长。
除了练空手道,Elaxia其他时间都花在了学习和找MM上面,所有他想请你帮忙为他设计一套满足他要求的晨跑计划。

输入
第一行2个数n,m。表示十字路口数和街道数。
接下来m行,每行3个数a,b,c,表示十字路口a和十字路口b之间有条长度为c的街道(单向)。

输出
2个数,第一个数为最长周期的天数,第二个数为满足最长天数的条件下最短的路程长度。

输入样例
7 10
1 2 1
1 3 1
2 4 1
3 4 1
4 5 1
4 6 1
2 5 5
3 6 6
5 7 1
6 7 1

输出样例
2 11

N<=200  M<=20000

听某大佬说过 网络流用vector一般要比链表快

于是我试了试 结果如下

都开了O2 vector直接起飞

直冲Rank 1 (-_-)

  1 #include<queue>
  2 #include<cstdio>
  3 #include<iostream>
  4 #define MAXN 20010
  5
  6 using namespace std;
  7
  8 const int INF=0x7fffffff;
  9 const int N=210;
 10
 11 struct JSF {
 12     int to;
 13     int next;
 14     int fee;
 15     int val;
 16 };
 17
 18 JSF e[MAXN<<1];
 19
 20 int head[MAXN<<1],tot=1;
 21
 22 int n,m,a,b,c,src,decc,ans1,ans2;
 23
 24 int dis[N<<1],pre[N<<1];
 25
 26 bool vis[N<<1];
 27
 28 queue<int> q;
 29
 30 inline void read(int&x) {
 31     int f=1;x=0;char c=getchar();
 32     while(c>‘9‘||c<‘0‘) {if(c==‘-‘) f=-1;c=getchar();}
 33     while(c>=‘0‘&&c<=‘9‘) {x=(x<<1)+(x<<3)+c-48;c=getchar();}
 34     x=x*f;
 35 }
 36
 37 inline void add(int x,int y,int v,int f) {
 38     e[++tot].to=y;
 39     e[tot].fee=f;
 40     e[tot].val=v;
 41     e[tot].next=head[x];
 42     head[x]=tot;
 43 }
 44
 45 inline void add_edge(int x,int y,int v,int f) {
 46     add(x,y,v,f);add(y,x,0,-f);
 47 }
 48
 49 bool spfa() {
 50     for(int i=1;i<=n<<1;i++) dis[i]=INF,vis[i]=false,pre[i]=-1;
 51     while(!q.empty()) q.pop();
 52     q.push(src);
 53     vis[src]=true;
 54     dis[src]=0;
 55     pre[src]=0;
 56     while(!q.empty()) {
 57         int u=q.front();
 58         q.pop();
 59         vis[u]=false;
 60         for(int i=head[u];i;i=e[i].next) {
 61             int to=e[i].to;
 62             if(e[i].val&&dis[to]>dis[u]+e[i].fee) {
 63                 dis[to]=dis[u]+e[i].fee;
 64                 pre[to]=i;
 65                 if(!vis[to]) {
 66                     q.push(to);
 67                     vis[to]=true;
 68                 }
 69             }
 70         }
 71     }
 72     return dis[decc]!=INF;
 73 }
 74
 75 inline int change() {
 76     int Flow=INF;
 77     for(int i=pre[decc];i;i=pre[e[i^1].to])
 78       Flow=min(Flow,e[i].val);
 79     ans1++;
 80     for(int i=pre[decc];i;i=pre[e[i^1].to]) {
 81         e[i].val-=Flow;
 82         e[i^1].val+=Flow;
 83     }
 84     return Flow*dis[decc];
 85 }
 86
 87 inline void ISPA() {
 88     while(spfa())
 89       ans2+=change();
 90     return;
 91 }
 92
 93 inline int hhh() {
 94     freopen("run.in","r",stdin);
 95     freopen("run.out","w",stdout);
 96     read(n);read(m);
 97     src=1;decc=n<<1;
 98     for(int i=1;i<=m;i++) {
 99         read(a);read(b);read(c);
100         add_edge(a+n,b,1,c);
101     }
102     for(int i=2;i<n;i++) add_edge(i,i+n,1,0);
103     add_edge(1,1+n,INF,0);
104     add_edge(n,n<<1,INF,0);
105     ISPA();
106     printf("%d %d\n",ans1,ans2);
107     return 0;
108 }
109
110 int sb=hhh();
111 int main() {;}

链表

  1 /*
  2     事实证明 vector 的确 比链表 跑得快
  3     开O2后直接起飞
  4 */
  5 #include<queue>
  6 #include<vector>
  7 #include<cstdio>
  8 #include<iostream>
  9 #define MAXN 20010
 10
 11 using namespace std;
 12
 13 const int INF=0x7fffffff;
 14 const int N=810;
 15
 16 int n,m,a,b,c,ans1,ans2,decc,src;
 17
 18 int dis[N<<1],pre[N<<1],f[2][N<<1][N<<1];
 19
 20 bool vis[N<<1];
 21
 22 vector<int> e[MAXN];
 23
 24 queue<int> q;
 25
 26 inline void read(int&x) {
 27     int f=1;x=0;char c=getchar();
 28     while(c>‘9‘||c<‘0‘) {if(c==‘-‘) f=-1;c=getchar();}
 29     while(c>=‘0‘&&c<=‘9‘) {x=(x<<1)+(x<<3)+c-48;c=getchar();}
 30     x=x*f;
 31 }
 32
 33 inline void add(int x,int y,int v,int fee) {
 34     e[x].push_back(y);
 35     f[0][x][y]=v;
 36     f[1][x][y]=fee;
 37 }
 38
 39 inline void add_edge(int x,int y,int v,int f) {
 40     add(x,y,v,f);add(y,x,0,-f);
 41 }
 42
 43 bool spfa() {
 44     for(int i=1;i<=n<<1;i++) dis[i]=INF,vis[i]=false,pre[i]=-1;
 45     while(!q.empty()) q.pop();
 46     q.push(src);
 47     dis[src]=0;
 48     vis[src]=true;
 49     pre[src]=0;
 50     while(!q.empty()) {
 51         int u=q.front();
 52         q.pop();
 53         vis[u]=false;
 54         for(int i=0;i<e[u].size();i++) {
 55             int to=e[u][i];
 56             if(f[0][u][to]&&dis[to]>dis[u]+f[1][u][to]) {
 57                 dis[to]=dis[u]+f[1][u][to];
 58                 pre[to]=u;
 59                 if(!vis[to]) {
 60                     q.push(to);
 61                     vis[to]=true;
 62                 }
 63             }
 64         }
 65     }
 66     return dis[decc]!=INF;
 67 }
 68
 69 inline int change() {
 70     int flow=INF;ans1++;
 71     for(int i=decc;i!=1;i=pre[i])
 72       flow=min(flow,f[0][pre[i]][i]);
 73     for(int i=decc;i!=1;i=pre[i]) {
 74         f[0][pre[i]][i]-=flow;
 75         f[0][i][pre[i]]+=flow;
 76     }
 77     return flow*dis[decc];
 78 }
 79
 80 inline void ISPA() {
 81     while(spfa())
 82       ans2+=change();
 83     return;
 84 }
 85
 86 inline int hhh() {
 87     freopen("run.in","r",stdin);
 88     freopen("run.out","w",stdout);
 89     read(n);read(m);
 90     src=1;decc=n<<1;
 91     for(int i=1;i<=m;i++) {
 92         read(a);read(b);read(c);
 93         add_edge(a+n,b,1,c);
 94     }
 95     for(int i=2;i<n;i++) add_edge(i,i+n,1,0);
 96     add_edge(1,1+n,INF,0);
 97     add_edge(n,n<<1,INF,0);
 98     ISPA();
 99     printf("%d %d\n",ans1,ans2);
100     return 0;
101 }
102
103 int sb=hhh();
104 int main() {;}

vector

时间: 2024-10-07 03:58:06

[SDOI2009] 晨跑 (费用流) ---链表 VS Vector的相关文章

BJOJ1877|SDOI2009晨跑|费用流

DescriptionElaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑.仰卧起坐等 等,不过到目前为止,他坚持下来的只有晨跑. 现在给出一张学校附近的地图,这张地图中包含N个十字路口和M条街道,Elaxia只能从 一个十字路口跑向另外一个十字路口,街道之间只在十字路口处相交.Elaxia每天从寝室出发 跑到学校,保证寝室编号为1,学校编号为N. Elaxia的晨跑计划是按周期(包含若干天)进行的,由于他不喜欢走重复的路线,所以 在一个周期内,每天的晨跑路线都不会相交(在十字

B1877 [SDOI2009]晨跑 费用流

其实之前写过一个板子,但是一点印象都没有,所以今天重写了一下,顺便把这个题当成板子就行了. 其实费用流就是把bfs换成spfa,但是中间有一个原则,就是费用优先,在费用(就是c)上跑spfa,顺便求出流量. 其实理解起来还算简单,就是先spfa找最小费用路径,然后在路径上找能跑的最大流. 题干: Description Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑.仰卧起坐等 等,不过到目前为止,他 坚持下来的只有晨跑. 现在给出一张学校附近的地图,这张地图中包含N个十

BZOJ1877 SDOI2009 晨跑 费用流

题意:给定一张有向图,求1到N:1.最多有多少条不相交的路径  2.在第一问的基础上,求所有路径的最小距离和 题解:拆点之后费用流裸题 #include <queue> #include <cstdio> #include <cstring> #include <cstdlib> #include <climits> #include <iostream> #include <algorithm> using namesp

[SDOI2009][bzoj1877] 晨跑 [费用流]

题面: 传送门 思路: 一个点只能走一回,路径不能相交...... 显然可以转化为网络流的决策来做 我们构建一个网络,令其最大流等于最大的跑步天数即可 怎么构造呢? 对于每个点只能走一次的限制,可以考虑拆点,将每个点(除了起点和终点)拆成两个,中间连一条容量为1的边,就可以了 同时,因为要求走的距离最短,那么给每一条原图中的边赋一个费用,把最大流改成费用流即可 这道题有一个值得深思的地方:是题目中的哪个点让你想到要用网络流而不是别的算法来做的? 这道题我实际上是抱着"网络流那么厉害,说不定就做得

BZOJ 1877: [SDOI2009]晨跑( 最小费用最大流 )

裸的费用流...拆点, 流量限制为1, 最后的流量和费用即答案. ---------------------------------------------------------------------- #include<bits/stdc++.h> using namespace std; const int maxn = 409; const int INF = 1 << 30; struct edge { int to, cap, cost; edge *next, *r

BZOJ1877: [SDOI2009]晨跑

1877: [SDOI2009]晨跑 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 1024  Solved: 540[Submit][Status] Description Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑.仰卧起坐等 等,不过到目前为止,他坚持下来的只有晨跑. 现在给出一张学校附近的地图,这张地图中包含N个十字路口和M条街道,Elaxia只能从 一个十字路口跑向另外一个十字路口,街道之间只在十字路口处相交.E

1877: [SDOI2009]晨跑

1877: [SDOI2009]晨跑 Description Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑.仰卧起坐等 等,不过到目前为止,他 坚持下来的只有晨跑. 现在给出一张学校附近的地图,这张地图中包含N个十字路口和M条街道,Elaxia只能从 一 个十字路口跑向另外一个十字路口,街道之间只在十字路口处相交.Elaxia每天从寝室出发 跑到学校,保证寝室 编号为1,学校编号为N. Elaxia的晨跑计划是按周期(包含若干天)进行的,由于他不喜欢走重复的路线,所以

【bzoj1150】[CTSC2007]数据备份Backup 模拟费用流+链表+堆

题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏的乐趣.已知办公楼都位于同一条街上.你决定给这些办公楼配对(两个一组).每一对办公楼可以通过在这两个建筑物之间铺设网络电缆使得它们可以互相备份.然而,网络电缆的费用很高.当地电信公司仅能为你提供 K 条网络电缆,这意味着你仅能为 K 对办公楼(或总计2K个办公楼)安排备份.任一个办公楼都属于唯一的配

【费用流】BZOJ1877[SDOI2009]-晨跑

[题目大意] Elaxia每天从寝室出发跑到学校,保证寝室编号为1,学校编号为N. Elaxia的晨跑计划是按周期(包含若干天)进行的,由于他不喜欢走重复的路线,所以在一个周期内,每天的晨跑路线都不会相交(在十字路口处),寝室和学校不算十字路口.表示路口a和路口b之间有条长度为c的街道(单向),求出最长周期的天数和满足最长天数的条件下最短的路程长度. [思路] 拆点.我们可以将每个路口拆成两个点(i)和(i+N).由于Ai与Bi之间有长度为C的街道,则在(Ai)和(Bi+N)之间添加一条容量为1