【ICPC2015沈阳M】Meeting

原题:

【ICPC2015沈阳M】Meeting

 

 题意:

有n个草地和m个集合,每个集合内有若干个草地,表示这些草地可以任意互通,一个草地可以出现在多个集合中,问你从草地1到草地n最少需要经过多少个草地

 

每个集合开一个爸爸节点,集合内的点上车花1块钱,下车不花钱,然后堆优化的dij即可

 

代码:

【ICPC2015沈阳M】Meeting
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cmath>
  5 using namespace std;
  6 #define LL long long
  7 const LL oo=1LL*1000000000*1000000000;
  8 struct edg{int y,v,nxt;}e[2100000];  int lk[2100000],ltp=0;
  9 void ist(int x,int y,int z){
 10     edg tmp;
 11     tmp.y=y,tmp.v=z,tmp.nxt=lk[x];
 12     e[++ltp]=tmp;  lk[x]=ltp;
 13     //e[++ltp]=(edg){y,z,lk[x]};  lk[x]=ltp;
 14 }
 15 struct nds{
 16     int x;  LL y;
 17     bool operator<(nds z){  return y<z.y;}
 18     bool operator>(nds z){  return y>z.y;}
 19 };
 20 nds hp[2100000];  int sz=0;
 21 void psh(nds z){
 22     hp[++sz]=z;
 23     for(int i=sz;i>1 && hp[i]<hp[i>>1];i>>=1)  swap(hp[i],hp[i>>1]);
 24 }
 25 void pp(){
 26     hp[1]=hp[sz--];
 27     int x=1,mn=1;
 28     for(;;){
 29         mn=x;
 30         if((x<<1)<=sz && hp[x<<1]<hp[mn])  mn=(x<<1);
 31         if((x<<1|1)<=sz && hp[x<<1|1]<hp[mn])  mn=(x<<1|1);
 32         if(mn==x)  break;
 33         swap(hp[mn],hp[x]);
 34         x=mn;
 35     }
 36 }
 37 int n,m;
 38 LL dstc[2100000];
 39 LL a[2100000],b[2100000];
 40 void dij(int x){
 41     sz=0;
 42     for(int i=1;i<=m+n;++i)  dstc[i]=oo;
 43     dstc[x]=0;
 44     nds tmp;
 45     tmp.x=x,tmp.y=0;
 46     psh(tmp);
 47     //psh((nds){x,0});
 48     while(sz){
 49         while(sz && hp[1].y>dstc[hp[1].x]){
 50             pp();
 51         }
 52         if(!sz)  break;
 53         x=hp[1].x;  dstc[x]=hp[1].y;
 54         pp();
 55         for(int i=lk[x];i;i=e[i].nxt)if(dstc[x]+e[i].v<dstc[e[i].y]){
 56             dstc[e[i].y]=dstc[x]+e[i].v;
 57             nds tmp;
 58             tmp.x=e[i].y,tmp.y=dstc[e[i].y];
 59             psh(tmp);
 60             //psh((nds){e[i].y,dstc[e[i].y]});
 61         }
 62     }
 63 }
 64 void prvs(){
 65     ltp=0;
 66     for(int i=1;i<=m+n;++i)  lk[i]=0;
 67     sz=0;
 68 }
 69 int main(){
 70     int T;  cin>>T;
 71     for(int t=1;t<=T;++t){
 72         cin>>n>>m;
 73         prvs();
 74         int x,y,z;
 75         for(int i=1;i<=m;++i){
 76             scanf("%d%d",&z,&y);
 77             for(int j=1;j<=y;++j){
 78                 scanf("%d",&x);
 79                 ist(x,n+i,z);
 80                 ist(n+i,x,0);
 81             }
 82         }
 83         dij(1);
 84         for(int i=1;i<=m+n;++i)  a[i]=dstc[i];
 85         dij(n);
 86         for(int i=1;i<=m+n;++i)  b[i]=dstc[i];
 87         LL mn=oo;
 88         for(int i=1;i<=n;++i)  mn=min(mn,max(a[i],b[i]));
 89         int cnt=0;
 90         for(int i=1;i<=n;++i)if(max(a[i],b[i])==mn)  ++cnt;
 91         /*
 92         cout<<"=============="<<endl;
 93         for(int i=1;i<=n;++i)  cout<<a[i]<<" ";
 94         cout<<endl;
 95         for(int i=1;i<=n;++i)  cout<<b[i]<<" ";
 96         cout<<endl;
 97         cout<<"=============="<<endl;
 98         */
 99         printf("Case #%d: ",t);
100         if(mn==oo){
101             printf("Evil John\n");
102         }
103         else{
104             printf("%lld\n",mn);
105             int sb=0;
106             for(int i=1;i<=n;++i)if(max(a[i],b[i])==mn){
107                 ++sb;
108                 printf("%d",i);
109                 if(sb!=cnt)  printf(" ");
110             }
111             printf("\n");
112         }
113     }
114     return 0;
115 }
View Code

 

上一篇:Qt实现贴边隐藏


下一篇:实验5 模板类与多态