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 ...
随机推荐
- C++(MFC)
C++(MFC) 1.关联变量(与控件关联): (1)一组单选按钮:需要将第一个单选按钮的Group选项设为true,则单选按钮就为一组(组框为标示作用).选中第一个则为0,第二个为1,依次类推(P2 ...
- IR的评价指标—MAP,NDCG,MRR
http://www.cnblogs.com/eyeszjwang/articles/2368087.html MAP(Mean Average Precision):单个主题的平均准确率是每篇相关文 ...
- ubuntu 安装git
问题描述: ubuntu安装git 问题解决: (1)ubuntu下载git 注: 使用命令apt-get install git安装 (2)查看g ...
- MySQL主从关系设置(转)
来源:LAMP兄弟连 作者:李恺 http://***/php/bencandy.php?fid=70&id=635 要做MySQL主从关系的设置,那么就得有两台MySQL主机.所以在开始之前 ...
- linux下mysql的root密码忘记解决方
1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库. 因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于没有密码保护的 状态下,其他的用户也可以任意地登录 ...
- Java学习第三篇:类的三大特征,抽象类,接口,final关键字
一.类的三大特征 1.封装性 (1).什么是封装 封装就是把抽象出的数据和对数据的操作封装在一起, 数据被保护在内部, 程序的其他部分只有通过被授权的操作(成员方法), 才能对数据进行操作. (2). ...
- [主席树]ZOJ2112 && BZOJ1901 Dynamic Rankings
题意:n个数,q个询问 (n<=50000, q<=10000) Q x y z 代表询问[x, y]区间里的第z小的数 C x y 代表将(从左往右数)第x个数变成y 上篇介绍了在 ...
- hdu1102
http://acm.hdu.edu.cn/showproblem.php?pid=1102 最小生成树(模板题) 3 0 990 692 990 0 179 692 179 0 1 1 2 一共3个 ...
- hdu 1426 Sudoku Killer
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1426 #include<stdio.h> #include<math.h> #in ...
- lintcode :最长上升连续子序列
题目: 最长上升连续子序列 给定一个整数数组(下标从 0 到 n-1, n 表示整个数组的规模),请找出该数组中的最长上升连续子序列.(最长上升连续子序列可以定义为从右到左或从左到右的序列.) 样例 ...