HDU 5521 Meeting 最短路
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5521 Meeting 最短路相关的知识,希望对你有一定的参考价值。
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5521
题意;
给你一副图,n个节点,一个人在1,一个人在n问你在哪个节点相遇花的时间最短。
题解:
比较快想到的思路就是起点,终点都跑一遍最短路。
但是发现边太多,图建不出来。
重新构造一幅等价的图可以解决这道题:
为每一个集合建一个新节点,属于某个集合的节点,建一条权值为0的边到代表这个集合的新节点,同时新节点向属于这个集合的节点建一条权值为w(w为这个集合任意两点的距离)的边。
然后跑两次最短路。
证明:
属于集合的点到集合的距离自然为0,而集合到点的距离则表示着从该集合的另一个点到达这个点,所以距离为w。
代码:
#include<iostream> #include<cstdio> #include<vector> #include<algorithm> #include<cstring> #include<queue> #define X first #define Y second #define mp make_pair using namespace std; const int maxn = 2e5 + 10; const int INF = 0x3f3f3f3f; int n, m; vector<pair<int,int> > G[maxn]; int d1[maxn], d2[maxn],dd[maxn]; int inq[maxn]; int ans; void spfa(int s,int *d) { memset(inq, 0, sizeof(inq)); memset(d, 0x7f, sizeof(int)*maxn); queue<int> Q; Q.push(s), d[s] = 0, inq[s] = 1; while (!Q.empty()) { int u = Q.front(); Q.pop(); inq[u] = 0; for (int i = 0; i < G[u].size(); i++) { int v = G[u][i].X, w = G[u][i].Y; if (d[v] > d[u] + w) { d[v] = d[u] + w; if (!inq[v]) { inq[v] = 1, Q.push(v); } } } } } void init() { ans = INF; for (int i = 0; i < n + m; i++) G[i].clear(); } int main() { int tc,kase=0; scanf("%d", &tc); while (tc--) { scanf("%d%d", &n, &m); init(); for (int i = 0; i < m; i++) { int w, cnt,v; scanf("%d%d", &w, &cnt); for (int j = 0; j < cnt; j++) { scanf("%d", &v); v--; G[i + n].push_back(mp(v, w)); G[v].push_back(mp(i + n, 0)); } } spfa(0, d1); spfa(n - 1, d2); for (int i = 0; i < n; i++) { dd[i] = max(d1[i], d2[i]); ans = min(ans, dd[i]); } vector<int> vec; for (int i = 0; i < n; i++) if (dd[i] == ans) { vec.push_back(i + 1); } printf("Case #%d: ", ++kase); if (ans == INF) { printf("Evil John\n"); } else { printf("%d\n", ans); for (int i = 0; i < vec.size() - 1; i++) printf("%d ", vec[i]); printf("%d\n", vec[vec.size() - 1]); } } return 0; }
以上是关于HDU 5521 Meeting 最短路的主要内容,如果未能解决你的问题,请参考以下文章