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;
}

 

 

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