题意:题目大意:A,B两个人分别在1和n区。求碰面区间使得两人所花时间最短
分析: 因为是以集合给出,所以按集合中的边数两两建边会导致边数过多,所以一个集合添加一个缩点,到缩点的距离为当前集合的值
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long int ll;
typedef pair<int,int> P;
typedef pair<long long int ,int > PI;
#define INF 0x3f3f3f3f
#define maxn 200050
vector<P>E[maxn];
ll dis[maxn];
ll disc[maxn];
int T;
int n , m ;
void dijkstra(int s, ll *d)
{
for(int i = 0 ; i < maxn ; ++i)
d[i] = INF;
d[s] = 0;
priority_queue<PI ,vector<PI> , greater<PI> >Q;
Q.push(PI(0,s));
while(!Q.empty())
{
ll c = Q.top().first;
int u = Q.top().second;
Q.pop();
if( d[u] < c )continue;
for(int i = 0 ; i < E[u].size() ; ++i)
{
int v = E[u][i].first;
ll w = E[u][i].second;
if( d[v] > d[u] + w )
{
d[v] = d[u] + w;
Q.push(PI(d[v],v));
}
}
}
}
int main()
{
cin >> T;
int cas = 0;
while( T-- )
{
for(int i = 0 ; i< maxn ; ++i)E[i].clear();
cin >> n >> m ;
for(int i = 1 ; i <= m ; ++i)
{
int c , k ;
scanf("%d %d",&c,&k);
for(int j = 0 ; j < k ; ++j)
{
int b;
scanf("%d",&b);
E[i + n].push_back(P(b,c));
E[ b ].push_back(P(i+n,0));
}
}
dijkstra(1,dis);
dijkstra(n,disc);
ll ans = INF;
for(int i = 1 ; i <= n ; ++i){
ans = min(ans,max(dis[i],disc[i]));
}
printf("Case #%d: ",++cas);
if( ans == INF )
{
printf("Evil John\n");
continue;
}
else printf("%lld\n",ans);
priority_queue<int,vector<int>,greater<int> >Q;
for(int i = 1 ; i <= n ; ++i){
if( disc[i] <= ans && dis[i] <= ans ){
Q.push(i);
}
}
while( Q.size() > 1 ){
printf("%d ",Q.top());
Q.pop();
}
printf("%d\n",Q.top());Q.pop();
}
}