将每个集合抽象为一个点 将该集合中的点都挂到上面 不用两两建边
#include <bits/stdc++.h> using namespace std; #define ll long long #define N 0x3f3f3f3f3f3f3f3f struct node1 { int v; ll w; int next; }; struct node2 { bool friend operator < (node2 n1,node2 n2) { return n1.val>n2.val; } ll val; int id; }; priority_queue <node2> que; node1 edge[2000010]; ll dis1[200010],dis2[200010]; int first[200010],book[200010],ans[100010]; int n,m,num; void addedge(int u,int v,ll w) { edge[num].v=v; edge[num].w=w; edge[num].next=first[u]; first[u]=num++; return; } void dijkstra(int ss,ll* dis) { node2 cur,tem; ll w; int i,u,v; while(!que.empty()) que.pop(); for(i=1;i<=n+m;i++) dis[i]=N; memset(book,0,sizeof(book)); tem.id=ss,tem.val=0; que.push(tem); dis[ss]=0; while(!que.empty()) { cur=que.top(); que.pop(); u=cur.id; if(book[u]) continue; //printf("***%d***\n",u); book[u]=1; for(i=first[u];i!=-1;i=edge[i].next) { v=edge[i].v,w=edge[i].w; if(!book[v]&&dis[v]>dis[u]+w) { //printf("***%d %lld***\n",v,w); dis[v]=dis[u]+w; tem.id=v,tem.val=dis[v]; que.push(tem); } } } return; } int main() { ll val,minn; int t,cas,i,j,gou,id,cnt; scanf("%d",&t); for(cas=1;cas<=t;cas++) { scanf("%d%d",&n,&m); memset(first,-1,sizeof(first)); num=0; for(i=1;i<=m;i++) { scanf("%lld%d",&val,&gou); for(j=1;j<=gou;j++) { scanf("%d",&id); addedge(id,n+i,val); addedge(n+i,id,0); } } dijkstra(1,dis1); dijkstra(n,dis2); minn=N,cnt=0; for(i=1;i<=n;i++) { if(dis1[i]!=N&&dis2[i]!=N) { if(minn>max(dis1[i],dis2[i])) { minn=max(dis1[i],dis2[i]); cnt=1; ans[cnt]=i; } else if(minn==max(dis1[i],dis2[i])) { cnt++; ans[cnt]=i; } } } if(minn==N) { printf("Case #%d: Evil John\n",cas); } else { printf("Case #%d: %lld\n",cas,minn); for(i=1;i<=cnt-1;i++) { printf("%d ",ans[i]); } printf("%d\n",ans[i]); } } return 0; }