zoukankan      html  css  js  c++  java
  • HDU 5521 题解

    题意:给出n个点,John需要和一个住在第n个点的人在某个点碰面,再给出m个集合,每个集合中包含Si个点,这些点两两之间可以以ti时间互达,求两人需花费的最小时间,若无法走到第n个点,则输出Evil John.

    2<=N<=100000;1<=ti<=1e9;Si>0;Si<=1e6;

    1~6组数据,6000MS

     

    算法/思路:

    第一次见到这种套路的话还是蛮有趣的,对每个集合中两两点建边显然会被轻松TLE.

    使用最短路+虚拟节点:于是我们对每个集合建立一个虚拟节点,在每个集合中的节点与虚拟节点间连一条权值为t的边(最终答案要除以2),然后用spfa或者堆优化dijkstra,分别从1n为起点求一次最短路,对每个点取最大值,最后枚举点取最小值。时间复杂度O((m+n)log(m+n)),由上述描述,0<=m<=1e6.

    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<algorithm>
    using namespace std;
    int t,n,m,time,s,src;
    const int maxn=210000;
    vector<pair<int,int>> g[maxn];
    int ss;
    const long long inf=3e14;
    long long ans[maxn];
    long long dist[maxn];
    int jl[maxn];
    int tot;
    bool v[maxn];
    
    priority_queue <pair<long long,int>,vector<pair<long long,int> >,greater<pair<long long,int> > > dui;
    
    void dijkstra(){
        for (int i=1;i<=n+m;++i) dist[i]=inf;
        dist[src]=0;
        pair<long long,int> now;
        dui.push(make_pair(0,src));
        memset(v,false,sizeof(v));
        for (int i=1;i<=n+m;++i){
            if (dui.empty()) break;
            now=dui.top();dui.pop();
            while (v[now.second] && !dui.empty()) {now=dui.top();dui.pop();}
            if (v[now.second]) break;
            v[now.second]=true;
            for (int j=0;j<g[now.second].size();++j) if (!v[g[now.second][j].first])
                if (now.first+g[now.second][j].second<dist[g[now.second][j].first])
                    {    
                        dist[g[now.second][j].first]=now.first+g[now.second][j].second;dui.push(make_pair(dist[g[now.second][j].first],g[now.second][j].first));
                    }
        }
    }
    
    int main(){
        scanf("%d",&t);bool tmp;
        for (int q=1;q<=t;++q){
            for (int i=1;i<=maxn;++i) g[i].clear();
            scanf("%d%d",&n,&m);
            for (int i=1;i<=m;++i){
                scanf("%d%d",&time,&s);
                for (int j=1;j<=s;++j) {scanf("%d",&ss);g[i+n].push_back(make_pair(ss,time));g[ss].push_back(make_pair(i+n,time));}
                
            }
            long long pans=inf;
            while(dui.size()) dui.pop();
            src=1;dijkstra();for (int i=1;i<=n;++i) ans[i]=dist[i];
            while(dui.size()) dui.pop();
            src=n;dijkstra();for (int i=1;i<=n;++i) ans[i]=max(dist[i],ans[i]);
            for (int i=1;i<=n;++i) 
                if (pans==inf||ans[i]<pans )  {
                    pans=ans[i];tot=1;jl[tot]=i;
                }    else if(ans[i]==pans) jl[++tot]=i;
            printf("Case #%d: ",q);
            if (pans==inf) printf("Evil John
    "); else {
                printf("%lld
    ",pans/2);
                for (int i=1;i<=tot-1;++i) printf("%d ",jl[i]);
                printf("%d
    ",jl[tot]);
            }
        }
        return 0;
    }
  • 相关阅读:
    初学flask
    第一次使用pyqt5解决的几个小问题
    一些细节
    关于random
    go语言 方法
    go 语言 struct 另类构造函数 继承
    go 语言 链表 的增删改查
    go 语言 链表
    go 语言struct
    无题
  • 原文地址:https://www.cnblogs.com/terra/p/7067535.html
Copyright © 2011-2022 走看看