学习最短路建图 HUD 5521

时间:2022-07-02 07:42:28

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跑两次就好了= =

//看看会不会爆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\n")
const LL inf = 1e17;
const int maxn = 2e6 + ;
struct Edge{
int from, to; LL val;
Edge(int f = , int t = , LL val = ): from(f), to(t), val(val){}
};
struct Point{
int from; LL val;
Point(int f = , LL val = ): 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 = ; 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 = ; i <= n + m; i++){
d[i] = inf;
}
d[s] = ;
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 = ; 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();
for (int i = ; i <= n; i++) d1[i] = d[i];
dijstra(n);
for (int i = ; i <= n; i++) d2[i] = d[i];
LL minival = inf;
for (int i = ; i <= n; i++){
minival = min(minival, max(d1[i], d2[i]));
}
if (minival == inf) {
printf("Case #%d: Evil John\n", ++kase);
return ;
}
vector<int> v;
for (int i = ; i <= n; i++){
if (minival == max(d1[i], d2[i])) v.push_back(i);
}
printf("Case #%d: %I64d\n", ++kase, minival / );
for (int i = ; i < v.size(); i++){
printf("%d%c", v[i], i == v.size() - ? '\n' : ' ');
}
} int main(){
int T; cin >> T;
while (T--){
scanf("%d%d", &n, &m);
for (int i = ; i <= n + m; i++) G[i].clear();
for (int i = ; i <= m; i++){
LL t; int cnt; scanf("%I64d%d", &t, &cnt);
for (int j = ; j <= cnt; j++){
scanf("%d", a + j);
}
build(i + n, cnt, t);
}
solve();
}
return ;
}