noip模拟测试 生产
4136: [NOIP2016模拟赛No.6]生产
时间限制: 1 Sec 内存限制: 24 MB
提交: 63 解决: 28
[提交][状态][讨论版]题目描述
工厂为了生产一种复杂的产品,给各个生产部门制定了详细的生产计划。那么,就经常会有生产部门要把产品送到另一个生产部门作为原料。这是一个注重产品质量的工厂,所以每当有产品要从A部门运到B部门时,都要先从A部门送到质量检验处,检验合格后再从质量检验处运到B部门。
有些部门之间有传送带连接,厂长想知道每次将产品从一个部门运送到另一个部门最少需要多长时间。
输入
第一行两个整数n、m,n表示部门数量,m表示传送带数量。出于方便,1号部门是质量检验处。
接下来m行,每行三个整数u、v、w,表示有一条从u部门到v部门的传送带,传送过去需要w个单位时间。注意传送带是单向的。
接下来一个整数q,表示有q次运送。
接下来q行,每行两个数a、b,表示这一次要将产品从a部门运送到b部门。
输出
输出q行,每行一个整数,表示这次运送最少需要的时间。若没有传送方案,输出-1。
样例输入
5 5 1 2 3 1 3 5 4 1 7 5 4 1 5 3 1 3 4 2 5 3 2 3
样例输出
10 13 -1
提示
30%的数据,n≤100,m≤500,w=1
60%的数据,n≤100,m≤5000
另20%的数据,q=1
100%的数据,2≤n≤3000,m≤100000,2≤a,b≤n,
q≤100000,1≤u,v≤n,1≤w≤10000
有些部门之间可能有多条传送带。
工厂的员工都非常尽职尽责,他们的认真和热情决定了产品的完美,所以不必考虑产品不合格的情况。
先建一发图,然后求出dis数组,然后再建反向图,再跑一边最短路,对于询问就是a到1的距离加上1到b的距离。
(好像我写了一个不伦不类的东西。。。这好像叫做SPFA的dijkstra。。。)
(为什么用heap来维护点的编号啊喂)
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <queue> 7 8 using namespace std; 9 10 #define FILE_NAME "production" 11 12 #define INF 0x3f3f3f3f 13 14 const int N = 110000; 15 16 int n, m, q, head[N], rest[N], to[N], len[N], x[N], y[N], z[N], tot; 17 int dis[N], dis2[N]; 18 bool vis[N]; 19 20 void init(){ 21 tot = 0; 22 memset(head, 0, sizeof(head)); 23 memset(dis, 0x3f, sizeof(dis)); 24 memset(vis, 0, sizeof(vis)); 25 } 26 27 void add(int u, int v, int w){ 28 tot ++; 29 to[tot] = v; 30 len[tot] = w; 31 rest[tot] = head[u]; 32 head[u] = tot; 33 } 34 35 36 37 priority_queue<int> heap; 38 39 void dijkstra(){ 40 heap.push(vis[1] = 1); 41 dis[1] = 0; 42 while(heap.size()){ 43 int u = heap.top(); 44 heap.pop(); 45 vis[u] = 0; 46 for(int i = head[u] ; i ; i = rest[i]){ 47 int v = to[i]; 48 if(dis[v] > dis[u] + len[i]){ 49 dis[v] = dis[u] + len[i]; 50 if(!vis[v]){ 51 vis[v] = 1; 52 heap.push(v); 53 } 54 } 55 } 56 } 57 } 58 59 void work(){ 60 init(); 61 for(int i = 1 ; i <= m ; i ++)add(x[i], y[i], z[i]); 62 dijkstra(); 63 64 for(int i = 1 ; i <= n ; i ++)dis2[i] = dis[i]; 65 66 init(); 67 for(int i = 1 ; i <= m ; i ++)add(y[i], x[i], z[i]); 68 dijkstra(); 69 70 } 71 72 int ask(int a, int b){ 73 /* 74 dis : 所有点到1的最短路 75 dis2 : 1到所有点的最短路 76 */ 77 if(dis[a] == INF || dis2[b] == INF){ 78 return -1; 79 } 80 return dis[a] + dis2[b]; 81 } 82 83 int main(){ 84 freopen(FILE_NAME ".in", "r", stdin); 85 freopen(FILE_NAME ".out", "w", stdout); 86 87 scanf("%d%d", &n, &m); 88 for(int i = 1 ; i <= m ; i ++){ 89 scanf("%d%d%d", &x[i], &y[i], &z[i]); 90 } 91 work(); 92 scanf("%d", &q); 93 for(int i = 1, a, b ; i <= q ; i ++){ 94 scanf("%d%d", &a, &b); 95 printf("%d\n", ask(a, b)); 96 } 97 return 0; 98 }