http://acm.hdu.edu.cn/showproblem.php?pid=5521
题意:就是问你从1和n两个地方出发,在那个点见面时间最短,若有时间相等的点 按升序输出点
存图难,算法就是dij。存图看了大佬的博客,意思是说如果直接存图 会存n*n的边 笋干爆炸,因为是集合这种,所以直接每个集合建立一个虚点,再把集合里的点连起来,相应的集合点连虚点边为给定权值,而虚点连集合点为0即可 ,最后变成n*2存图。注意vector的清空和 dis数组的初始化 结点个数应该变为n+m个
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<vector>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e6+10;
struct edge{
int v;
int w;
edge(int v=0,int w=0):v(v),w(w){
}
};
vector<edge> e[maxn];
struct qnode{
int u;
int w;
qnode(int u=0,int w=0):u(u),w(w){}
bool operator < (const qnode& a) const{
return w>a.w;
}
};
struct node{
int id;
int num;
}s[maxn];
int dis[maxn];
int ans[maxn];
int n,m;
bool cmp(node a,node b){
if(a.num==b.num) return a.id<b.id;
else return a.num<b.num;
}
void dij(int s,int n){
for(int i=1;i<=n;i++){
dis[i]=inf;
}
dis[s]=0;
priority_queue<qnode> q;
while(!q.empty()){
q.pop();
}
q.push(qnode(s,0));
while(!q.empty()){
qnode tmp=q.top();
q.pop();
int u=tmp.u;
int size=e[u].size();
for(int i=0;i<size;i++){
int v=e[u][i].v;
int w=e[u][i].w;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
q.push(qnode(v,dis[v]));
}
}
}
}
int main(){
int t;
scanf("%d",&t);
int kase=1;
while(t--){
scanf("%d%d",&n,&m);
for(int i=0;i<=n+m;i++){//注意 清空
e[i].clear();
}
for(int i=1;i<=m;i++){
int x;
int y;
scanf("%d%d",&x,&y);
for(int j=1;j<=y;j++){
int z;
scanf("%d",&z);
e[z].push_back(edge(n+i,x));
e[n+i].push_back(edge(z,0));
}
}
dij(1,n+m);///注意
for(int i=1;i<=n;i++){
ans[i]=dis[i];
}
dij(n,n+m);//注意
int cnt=inf;
int mx=0;
int l=0;
int flag=0;
for(int i=1;i<=n;i++){
if(ans[i]!=inf&&dis[i]!=inf){
flag=1;
int kk=max(ans[i],dis[i]);
s[l].id=i;
s[l].num=kk;
l++;
}
}
printf("Case #%d: ",kase++);
if(flag==0) {
printf("Evil John\n");
continue;
}
sort(s,s+l,cmp);
int o=s[0].num;//最短路
printf("%d\n",o);
printf("%d",s[0].id);
for(int i=1;i<n;i++){
if(s[i].num==o) printf(" %d",s[i].id);
else break;
}
printf("\n");
}
}