HDU

来源:互联网 发布:简谱制作软件安卓版 编辑:程序博客网 时间:2024/06/11 03:55

Meeting

题目传送门
题意:有n个点,点按照1-n标号,m个集合,每个集合里面的点之间的距离都相等,有两个人,一个在1,另一个在n,他们要见面,且见面地点只能在点上,现在给出每个集合里面的点以及他们之间相等的距离,求他们见面的所需的最小时间和地点。
思路:很容易想到,分别从1开始和n开始做最短路,再从dis1和disn中取最大(实际时间为两者之间最大的),再取最小即可。但如果按照每个集合里面的点之间两两之间建图的话,边数太多会超时。实际上这样建图有很多边是多余的。可以知道,只要到达该集合,则需要花费给定时间time就可以到达该集合任意一点,所以我们可以把集合看作一个额外的点,集合里面的点到该点要花费time,而集合到该点则需0,如此建一个有向图既满足题目要求又大大减少的边数。

#include <iostream>#include <fstream>#include <cstdio>#include <cstring>#include <queue>#include <stack>#include <vector>#include <map>#include <set>#include <cmath>#include <algorithm>#include <functional>#define inf 0x3f3f3f3fusing namespace std;typedef long long ll;const int MAXN=1e6+10;const int MAX=1e6+10;const double eps=1e-6;int n,m,point;int dis[MAX],dis1[MAX],disn[MAX];int first[MAX],num;struct EDGE{    int v,w,next;}edge[MAXN*5];typedef pair<int,int>P;struct NODE{    int Time,id;}ans[MAX];void init(){    num=0;    memset(first,-1,sizeof(first));}void addedge(int u,int v,int w){    edge[num].v=v;    edge[num].w=w;    edge[num].next=first[u];    first[u]=num++;}void dijkstra(int s){    priority_queue<P,vector<P>,greater<P> >q;    dis[s]=0;    q.push(P(0,s));    while(q.size()){        P t=q.top();        q.pop();        int u=t.second;        if(dis[u]<t.first)            continue;        for(int i=first[u];i!=-1;i=edge[i].next){            int v=edge[i].v;            int w=edge[i].w;            if(dis[v]>dis[u]+w){                dis[v]=dis[u]+w;                q.push(P(dis[v],v));            }        }    }}int main(){    #ifdef ONLINE_JUDGE    #else    freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    #endif    int T,flag=1;    cin>>T;    while(T--){        printf("Case #%d: ", flag++);        cin>>n>>m;        init();        point=n+1;        int far,num,t;        for(int i=1;i<=m;i++){            scanf("%d%d",&far,&num);            for(int j=1;j<=num;j++){                scanf("%d",&t);                addedge(t,point,far);                addedge(point,t,0);            }            point++;        }        point--;        fill(dis,dis+point+1,inf);        dijkstra(1);            for(int i=1;i<=n;i++)            dis1[i]=dis[i];        fill(dis,dis+point+1,inf);        dijkstra(n);            for(int i=1;i<=n;i++)            disn[i]=dis[i];        int minn=inf;        for(int i=1;i<=n;i++){            dis[i]=max(dis1[i],disn[i]);            if(minn>dis[i])                minn=dis[i];         }        if(dis1[n]==inf)            cout<<"Evil John"<<endl;        else{            cout<<minn<<endl;int flag=0;            for(int i=1;i<=n;i++){                if(minn!=dis[i])    continue;                if(flag)                    cout<<" "<<i;                else                    cout<<i,flag=1;            }            cout<<endl;        }    }    return 0;   }
原创粉丝点击