ACM - ICPC World Finals 2013 C Surely You Congest
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf
题目翻译:
试题来源
ACM/ICPC World Finals 2013 C
问题描述
你现在要为智能汽车负责设计一种很高级的集中管理系统。目的是利用全球信息指导早上从郊区赶往市中心的乘客如何在避免交通堵塞的情况下更好地到达城市中心。
不幸的是,乘客们对城市非常了解,而且都相当自私,你不能简单地甩给他们一条比平常走的还要长的路径(否则他们会直接无视你的指导),所以只能说服他们改走另外一条长度相同的路径。
城市的道路网络由路口和连接它们的双向道路组成,通过不同的道路所需时间是不同的。所有乘客都会从各自的路口出发,当然不同的乘客出发的路口可能不同。但是所有乘客都会在同一个地点结束他们的旅程,那就是位于路口1的市中心。如果两个乘客试图在相同的时间,从同一方向,开始沿着相同的道路移动,就会出现堵塞——这是你必须避免种情况的。但是,两名乘客可以在同一时间通过同一个路口,或者在不同时间从同一条道路沿同一方向出发。
请确定最多能有多少人能够在没有堵塞的前提下开车前往市中心。注意,所有乘客刚好在同一时间从他们所在路口出发,而且乘客只会走能够最快到达路口1的路径。
在图C.1中,汽车图案标记了每名乘客最开始所在的路口,其中一辆车已经在市中心了。而路口4的车辆,可以走通过路口3的红色的点线,或者通过路口2的蓝色虚线。但是剩下的两辆车不可能在避免堵塞的前提下前往市中心。所以,在避免堵塞的情况下,最多只有3辆车能够抵达位于路口1的市中心。
输入格式
输入只会包含一组数据。第一行是三个正整数n,m,c,其中n(1≤n≤25000)是路口的个数,m(0≤m≤50000)是连接路口的道路的个数,而c(1≤c≤1000)则是乘客的个数。接下来m行,每行有三个正整数xi,yi,ti来描述一条道路,xi,yi是该道路连接的两个不同的路口,而ti,是开车通过这个道路的时间(两个方向的时间一样)。所有的路口都能够抵达市中心。最后一行的c个数,分别代表了c个乘客出发的路口。
输出格式
一个整数,表示在没有堵塞的情况下最多有多少乘客能够抵达市中心。
样例输入
3 3 2
1 2 42
2 3 1
2 3 1
2 3
样例输出
2
样例输入
4 4 5
1 2 5
1 3 4
4 2 5
4 3 6
4 4 4 4 1
样例输出
3
题目大意:
有n个城市和m条双向道路,每条道路的同一方向在同一时刻只能通过一辆车,现在有C辆车分布在这些城市中,他们想要到1号城市,并且一定要走最短路,问最多能有多少辆车可以按要求到达(不能被堵在半道上)
思路分析:
这道题十分类似于之前写过的SGU185,要求最短路的条数。所以一开始我们一1号城市为起点做一遍单源最短路,求出第 i 号城市到1 号城市的举例dist[i],并将所有不是在最短路上的边删去,然后准备求最大流。注意到拥堵只有可能发生在两辆车的起点具有相同的dist值的时候,所以我们可以按照dist值对车的起点排序,然后每次将相同dist值的车辆起点与源点相连,原来的删边之后的图照拷过去(注意到删边之后原来的无向图就变成了一棵有向树),然后求最大流即可
算法过程:
1、读入并建图,无向边按照两条有向边处理。
2、求所有点到1的最短路,使用SPFA或Dijkstra均可
3、将所有不可能在最短路上的边删掉(打上一个删除标记即可),剩下的图记为图M
4、读入c 辆车的起点,并按照这些店的dist值排序
5、将图M拷贝到当前的残量网络中(边的容量为1),新建源点并向dist值相同的起点连边,求一遍最大流,将最大流累加到答案中
6、重复第5步直至处理完所有的起点,输出答案
复杂度分析:
本题的理论渐进复杂度比较大,但事实上并没有被卡的那么死,建图的复杂度是O(m),最短路、删边复杂度O(m),第5步要做c次,它的复杂度是\(O(c*(m+n^{2}m))\),总渐进复杂度就是\(O(c*(m+n^{2}m))\)
参考代码:
- //date 20140122
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- using namespace std;
- const int maxn = ;
- const int maxm = ;
- const int maxc = ;
- const int INF = 0x7FFFFFFF;
- inline int getint()
- {
- int ans (); char w = getchar();
- while(w < '' || w > '')w = getchar();
- while('' <= w && w <= '')
- {
- ans = ans * + w - '';
- w = getchar();
- }
- return ans;
- }
- inline int min(int a, int b){return a < b ? a : b;}
- inline int max(int a, int b){return a > b ? a : b;}
- int n, m, c;
- struct edge
- {
- int u, v, w, c, next;
- }Etmp[maxm], E[maxm];
- int deled[maxm];
- int atmp[maxn], a[maxn];
- int nedgetmp, nedge;
- inline void addtmp(int u, int v, int w)
- {
- Etmp[++nedgetmp].v = v;
- Etmp[nedgetmp].u = u;
- Etmp[nedgetmp].w = w;
- Etmp[nedgetmp].next = atmp[u];
- atmp[u] = nedgetmp;
- }
- inline void add(int u, int v, int c)
- {
- E[++nedge].v = v;
- E[nedge].u = u;
- E[nedge].c = c;
- E[nedge].next = a[u];
- a[u] = nedge;
- }
- int dis[maxn];
- inline void SPFA()
- {
- static int q[maxn];
- static int inq[maxn];
- int l = , r = ;
- memset(dis, 0x7F, sizeof dis);
- memset(inq, , sizeof inq);
- dis[] = ; inq[] = ; q[] = ;
- while(l < r)
- {
- int x = q[(++l) % maxn];
- for(int i = atmp[x]; i; i = Etmp[i].next)
- if(dis[Etmp[i].v] > dis[x] + Etmp[i].w)
- {
- dis[Etmp[i].v] = dis[x] + Etmp[i].w;
- if(!inq[Etmp[i].v])
- {
- inq[Etmp[i].v] = ;
- q[(++r) % maxn] = Etmp[i].v;
- }
- }
- inq[x] = ;
- }
- for(int i = ; i <= n; ++i)printf("%d ", dis[i]);
- printf("\n");
- }
- inline void deledge()
- {
- memset(deled, , sizeof deled);
- for(int i = ; i <= nedgetmp; ++i)
- if(dis[Etmp[i].u] + Etmp[i].w > dis[Etmp[i].v])deled[i] = ;
- }
- int s, t;
- int lab[maxn], now[maxn];
- inline int label()
- {
- static int q[maxn];
- memset(lab, 0xFF, sizeof lab);
- int l = , r = ;
- q[] = s; lab[s] = ;
- while(l < r)
- {
- int x = q[++l];
- for(int i = a[x]; i; i = E[i].next)
- if(E[i].c > && lab[E[i].v] == -)
- {
- lab[E[i].v] = lab[x] + ;
- q[++r] = E[i].v;
- }
- }
- // for(int i = 1; i <= s; ++i)
- // fprintf(stderr, "%d ", lab[i]);
- // fprintf(stderr, "\n");
- return lab[t] != -;
- }
- int Dinic(int v, int f)
- {
- if(v == t)return f;
- int w, res = ;
- for(int i = now[v]; i; i = now[v] = E[i].next)
- if((E[i].c > ) && (f > ) && (lab[E[i].v] == lab[v] + ) && (w = Dinic(E[i].v, min(f, E[i].c))))
- {
- res += w;
- E[i].c -= w;
- E[i ^ ].c += w;
- f -= w;
- if(f == )break;
- }
- return res;
- }
- inline int max_flow()
- {
- int ans = ;
- while(label())
- {
- for(int i = ; i <= s; ++i)now[i] = a[i];
- ans += Dinic(s, INF);
- }
- // printf("%d\n", ans);
- return ans;
- }
- int tar[maxc];
- inline bool cmptar(int a, int b)
- {
- return dis[a] < dis[b];
- }
- inline void rebuild(int l, int r)
- {
- nedge = ;
- memset(a, , sizeof a);
- for(int i = ; i <= nedgetmp; ++i)
- if(!deled[i]){add(Etmp[i].v, Etmp[i].u, ); add(Etmp[i].u, Etmp[i]., );}
- for(int i = l; i <= r; ++i) {add(s, tar[i], ); add(tar[i], s, );}
- // for(int i = 2; i <= nedge; ++i)fprintf(stderr, "%d %d %d %d %d\n", i, E[i].u, E[i].v, E[i].c, E[i].next);
- }
- inline int solve()
- {
- int ans = , now = dis[tar[]], l = , r = ;
- for(int i = ; i <= c + ; ++i)
- {
- if(dis[tar[i]] == now)++r;
- else
- {
- if(l == r)++ans;
- else
- {
- rebuild(l, r);
- ans += max_flow();
- }
- now = dis[tar[i]];
- l = r = i;
- }
- }
- return ans;
- }
- int main()
- {
- freopen("congest.in", "r", stdin);
- freopen("congest.out", "w", stdout);
- n = getint(); m = getint(); c = getint();
- nedgetmp = ; nedge = ;
- s = n + ; t = ;
- for(int i = ; i <= m; ++i)
- {
- int x, y, t;
- x = getint(); y = getint(); t = getint();
- addtmp(x, y, t); addtmp(y, x, t);
- }
- SPFA();
- deledge();
- for(int i = ; i <= c; ++i)tar[i] = getint();
- sort(tar + , tar + c + , cmptar);
- int ans = solve();
- printf("%d\n", ans);
- return ;
- }
需要注意的问题:
1、之所以每次都需要重新建图,是因为跑完最大流之后我们剩下的图是上一次网络流的残量网络,图的结构已经发生了变化,所以必须重建
2、如果具有某一dist值的起点只有一个,那么它不会和其它车辆发生冲突,也自然无需重建图、求最大流了,直接将答案+1即可
3、从渐进复杂度角度来看这题肯定超时,所以无论用哪种网络流算法一定要将它优化到底(实践证明SAP的效果远不如Dinic)
ACM - ICPC World Finals 2013 C Surely You Congest的更多相关文章
- ACM - ICPC World Finals 2013 A Self-Assembly
原题下载 : http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 这道题其实是2013年我AC的第一道题,非常的开心,这 ...
- ACM - ICPC World Finals 2013 F Low Power
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 题目翻译: 问题描述 有n个机器,每个机器有2个芯片,每个 ...
- ACM - ICPC World Finals 2013 I Pirate Chest
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 题目翻译: 问题描述 海盗Dick受够了在公海上厮杀.抢劫 ...
- ACM - ICPC World Finals 2013 H Матрёшка
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 题目翻译: 问题描述 俄罗斯套娃是一些从外到里大小递减的传 ...
- ACM - ICPC World Finals 2013 D Factors
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 题目翻译: 问题描述 一个最基本的算数法则就是大于1的整数 ...
- ACM - ICPC World Finals 2013 B Hey, Better Bettor
原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 这题真心的麻烦……程序不长但是推导过程比较复杂,不太好想 ...
- [算法竞赛入门经典]Message Decoding,ACM/ICPC World Finals 1991,UVa213
Description Some message encoding schemes require that an encoded message be sent in two parts. The ...
- UVa210 Concurrency Simulator (ACM/ICPC World Finals 1991) 双端队列
Programs executed concurrently on a uniprocessor system appear to be executed at the same time, but ...
- 谜题 (Puzzle,ACM/ICPC World Finals 1993,UVa227)
题目描述:算法竞赛入门经典习题3-5 题目思路:模拟题 #include <stdio.h> #include <string.h> #define maxn 55 char ...
随机推荐
- listview中getview异步加载网络图片
前言:本以为异步加载挺简单,因为网上代码多,但真想要做好,还真不那么简单,从看代码到弄懂再到自己写,实在是有太多的东西需要学了,用了两天的时间,终于弄出来了,因为用到回调函数,所以理解起来可能难度有点 ...
- Win64位操作系统无法运行暗黑2战网D2GS的解决办法
前几天想在我的Win7 x64系统里做个战网自己玩,搭建完毕后进入战网创建房间出现经典的问题,“排队1”. 原因很清楚,就是D2GS无法启动:但是使用之前的各种办法尝试后无果,后来查看D2GS同目录下 ...
- 2014 Multi-University Training Contest 9
官方解题报告:http://blog.sina.com.cn/s/blog_6bddecdc0102uzwm.html Boring Sum http://acm.hdu.edu.cn/showpro ...
- centos6.5\win7双系统安装配置
一.安装所需软件 1.分区助手专业版PACNPro.exe(必需):用来对硬盘分区,将磁盘的一部分格式化成Linux可以识别的ext3格式 2.Ext2Fsd(硬盘安装必需,光盘安装不用):因为Win ...
- 让IE系列浏览器支持HTML5(share)
引用Google的html5.js文件 <!--[if IE]> <script src=”http://html5shiv.googlecode.com/svn/trunk/htm ...
- aChartEngine图表显示
android的数据报表显示 从图中,我们可以看出,绘制一个图表我们其实,我们只需要理解三个概念 1,ChartFactory ,传入XYMutilpleSeriesRenderer,XYMutilp ...
- PSYoungGen /PSOldGen/PSPermGen区别
原文地址:http://bbs.csdn.net/topics/210064791 谁能解译一下PSYoungGen /PSOldGen/PSPermGen区别及出现的问题? 看来没有收集到答案,查看 ...
- Eclipse jetty
下载Eclipse的Jetty插件run-jetty-run http://download.csdn.net/detail/zhwq1216/7995627 当修改文件时,不需要进行服务重启设置 R ...
- python自省指南
深入python中对自省的定义: python的众多强大功能之一,自省,正如你所知道的,python中万物皆对象,自省是指代码可以查看内存中以对象形式存在的其他模块和函数,获取它们的信息,并对它们进行 ...
- Linux和Linux之间共享目录
1.Linux 服务器端NFS服务器的配置 以root身份登陆Linux服务器,编辑/etc目录下的共享目录配置文件exports,指定共享目录及权限等. 执行如下命令编辑文件/etc/exports ...