hdu 5521 最短路dijkstra 特殊处理

Meeting

Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 5041    Accepted Submission(s): 1581


 

Problem Description

Bessie and her friend Elsie decide to have a meeting. However, after Farmer John decorated his
fences they were separated into different blocks. John's farm are divided into n blocks labelled from 1 to n .
Bessie lives in the first block while Elsie lives in the n -th one. They have a map of the farm
which shows that it takes they ti minutes to travel from a block in Ei to another block
in Ei where Ei (1≤i≤m) is a set of blocks. They want to know how soon they can meet each other
and which block should be chosen to have the meeting.

 

 

Input

The first line contains an integer T (1≤T≤6) , the number of test cases. Then T test cases
follow.

The first line of input contains n and m . 2≤n≤105 . The following m lines describe the sets Ei (1≤i≤m) . Each line will contain two integers ti(1≤ti≤109) and Si (Si>0) firstly. Then Si integer follows which are the labels of blocks in Ei . It is guaranteed that ∑mi=1Si≤106 .

 

 

Output

For each test case, if they cannot have the meeting, then output "Evil John" (without quotes) in one line.

Otherwise, output two lines. The first line contains an integer, the time it takes for they to meet.
The second line contains the numbers of blocks where they meet. If there are multiple
optional blocks, output all of them in ascending order.

 

 

Sample Input


 

2

5 4

1 3 1 2 3

2 2 3 4

10 2 1 5

3 3 3 4 5

3 1

1 2 1 2

 

 

Sample Output


 

Case #1: 3

3 4

Case #2: Evil John

 

 

Hint

In the first case, it will take Bessie 1 minute travelling to the 3rd block, and it will take Elsie 3 minutes travelling to the 3rd block. It will take Bessie 3 minutes travelling to the 4th block, and it will take Elsie 3 minutes travelling to the 4th block. In the second case, it is impossible for them to meet.

题意:

     给你n个城市,m个路径集合,要你从城市1走到城市n。每个路径集合包括一个T和S,接下来有S个城市。表示这S个城市之间的任意两个城市要行走要花费的时间是T,两个城市可能会出现在多个路径集合中。

 

做法:

    一道看似简单的最短路,但是有一个问题就是边集会因为两两要建立边的关系而数量庞大,这个时候就要做一个简单的处理,将一个路径集合中的点连接到第S+1个店上,时间变为原来的一半,如城市1,2,3之间要花费4小时,这个时候建立一个额外的店1',让这三个城市到达1'的时间变为2,这样的话1想到2就要经过1',让时间还是原来的4,这样的处理可以大大减少需要的边。然后只要把点1和点n丢进dijkstra跑一下就好了。

       需要的点最多有   n+最大路径集合数S=1e6+1e5.每个集合需要多加一个边

       需要的边最多有   S*2,建立双向边


代码如下:

#include<queue>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=1200005;
const int inf=0x3f3f3f3f;
ll dist1[maxn],t,distn[maxn];
int cnt,head[maxn],n,m,now,vis[maxn];
vector<int> ans;
struct node{
    int to,next,w;
}e[maxn*2];
struct  Node{
    int dis,id;
    Node(int dis,int id):dis(dis),id(id){}
    bool operator < (const Node &a)const{
        return dis>a.dis;
    }
};
void add(int u,int v,int w){
    e[cnt].to=v,e[cnt].w=w;
    e[cnt].next=head[u],head[u]=cnt++;
}
void init(){
    memset(head,-1,sizeof(head));
    cnt=0;
}
void dij(int st,ll dis[]){
    for(int i=1;i<=now;i++){
        dis[i]=1e18;
    }
    memset(vis,0,sizeof(vis));
    dis[st]=0;
    priority_queue<Node> q;
    q.push(Node(0,st));
    vis[st]=1;
    while(!q.empty()){
        int u=q.top().id; q.pop();
        vis[u]=1;
        for(int i=head[u];~i;i=e[i].next){
            int v=e[i].to;
            if(vis[v]) continue;
            if(dis[v]-(ll)e[i].w>dis[u]){
                dis[v]=dis[u]+(ll)e[i].w;
                q.push(Node(dis[v],v));
            }
        }
    }
}
int main(){
    int t,n,m,ti,s,x,cas=0;
    cin>>t;
    while(t--){
        init();
        scanf("%d%d",&n,&m);
        now=n;
        for(int i=1;i<=m;i++){
            scanf("%d%d",&ti,&s);
            now++;
            for(int j=0;j<s;j++){
                scanf("%d",&x);
                add(x,now,ti);
                add(now,x,ti);
            }
        }
        dij(1,dist1);
        dij(n,distn);
        printf("Case #%d: ",++cas);
        if(dist1[n]>=1e18){
            printf("Evil John\n");
        }
        else {
            ans.clear();
            ll now=1e18;
            for(int i=1;i<=n;i++){
                ll nowmin=max(dist1[i],distn[i]);
                if(now>nowmin/2){
                    ans.clear();
                    ans.push_back(i);
                    now=nowmin/2;
                }
                else if(now==nowmin/2){
                    ans.push_back(i);
                }
            }
            printf("%lld\n",now);
            for(int i=0;i<ans.size();i++){
                printf("%d%c",ans[i],i==ans.size()-1?'\n':' ');
            }
        }
    }
    return 0;
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章