http://acm.hdu.edu.cn/showproblem.php?pid=5521
题目大意:有n个点,m个集合,每个集合里面的点都两两可达且每条边权值都是val,有两个人A, B,A在pos=1,B在pos=n,问两者相遇的最短时间,输出相遇地点,如果有多个最短时间,输出的相遇地点按从小到大排序。
思路:因为集合暴力枚举点肯定mle。所以我不会TAT(我好菜啊)。于是看了一下别人的想法, 就是新建一个节点,然后让集合里面的所有节点都连向他, 然后权值定为和原来的权值一样,也是val(但是最后的ans要除以2)。 TAT,既然我都已经刷过网络流了,既然这个都没有想到
接下来就简单了。。。dijstra跑两次就好了= =
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//看看会不会爆int!数组会不会少了一维! //取物问题一定要小心先手胜利的条件 #include <bits/stdc++.h> using namespace std; #define LL long long #define ALL(a) a.begin(), a.end() #define pb push_back #define mk make_pair #define fi first #define se second #define haha printf("haha ") const LL inf = 1e17; const int maxn = 2e6 + 5; struct Edge{ int from, to; LL val; Edge(int f = 0, int t = 0, LL val = 0): from(f), to(t), val(val){} }; struct Point{ int from; LL val; Point(int f = 0, LL val = 0): from(f), val(val){} bool operator < (const Point &a) const{ return val > a.val; } }; vector<Edge> G[maxn]; int kase, n, m; int a[maxn]; void build(int newpoint, int cnt, LL t){ for (int i = 1; i <= cnt; i++){ G[a[i]].push_back(Edge(a[i], newpoint, t)); G[newpoint].push_back(Edge(newpoint, a[i], t)); } } LL d[maxn], d1[maxn], d2[maxn]; void dijstra(int s){ for (int i = 1; i <= n + m; i++){ d[i] = inf; } d[s] = 0; priority_queue<Point> que; que.push(Point(s, d[s])); while (!que.empty()){ Point u = que.top(); que.pop(); int len = G[u.from].size(); for (int i = 0; i < len; i++){ Edge p = G[u.from][i]; int v = p.to; if (d[v] > d[u.from] + p.val){ d[v] = d[u.from] + p.val; que.push(Point(v, d[v])); } } } } void solve(){ dijstra(1); for (int i = 1; i <= n; i++) d1[i] = d[i]; dijstra(n); for (int i = 1; i <= n; i++) d2[i] = d[i]; LL minival = inf; for (int i = 1; i <= n; i++){ minival = min(minival, max(d1[i], d2[i])); } if (minival == inf) { printf("Case #%d: Evil John ", ++kase); return ; } vector<int> v; for (int i = 1; i <= n; i++){ if (minival == max(d1[i], d2[i])) v.push_back(i); } printf("Case #%d: %I64d ", ++kase, minival / 2); for (int i = 0; i < v.size(); i++){ printf("%d%c", v[i], i == v.size() - 1 ? ' ' : ' '); } } int main(){ int T; cin >> T; while (T--){ scanf("%d%d", &n, &m); for (int i = 1; i <= n + m; i++) G[i].clear(); for (int i = 1; i <= m; i++){ LL t; int cnt; scanf("%I64d%d", &t, &cnt); for (int j = 1; j <= cnt; j++){ scanf("%d", a + j); } build(i + n, cnt, t); } solve(); } return 0; }