• hdu5521 ( Dijkstra )


    题目描述:

    给定一张图,问从1和n相遇的最短时间。

    这道题的输入比较特殊,不能直接存,所以怎么输入,怎么存取,只要可以访问到一个节点的相邻节点就可以,由于spfa算法的时间复杂度为m*n,而Dijkstra算法的时间复杂度为m*log(n),

    其实Dijkstra就是用优先队列替换掉了spfa中的普通队列,每次都是用权值最小的点去更新别人,可以这么理解,用用权值最小的点a去更新其他节点,在更新节点中必然会有一个节点已经是

    最短路,假设是b,因为源点到其他节点的距离+其他节点到b节点的距离 >  dist[a] + edge[a][b], 因为 源点到其他节点的距离 > dist[a] + edge[a][b];最多有10^6个点,那么可能就会有 10^12条边 ,时间复杂度为 10^12 * log(10^5) = 15*10^12;所以主要取决于有多少条边,分析一下如果一个节点已经更新了它所在集合中的其他点,那么这个集合中所有点之间的边就不会在更新了,假设a,b,c,d,e在一个集合里,集合之间的路径为edge,假设a是更新点,说明b,c,d,e的最短路大于a的最短路, 说明b,c,d的最短路一定是由a得到,而不是 b,c,d,Dis[a]+edge < Dist[k] +edge,k属于b,c,d。所以集合只会被访问一次。

    //有可能一个人在家等他
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <queue>
    #include <algorithm>
    #include <math.h>
    #define  maxn 1100000
    #define  LL    long long
    using namespace std;
    int t;
    int n,m;
    vector < int >  G[maxn];
    int tt[maxn],ss[maxn];
    vector < int >  Set[maxn];
    LL Dist[3][maxn];
    int vis[maxn];
    int VISIT[maxn];
     LL answer[maxn];
     LL ans[maxn];
    struct node
    {
        int u,dist;
        friend bool operator < (node a,node b)
        {
            return a.dist>b.dist;
        }
    };
    void init()
    {
        memset(vis,0,sizeof(vis));
        memset(VISIT,0,sizeof(VISIT));
    }
    
    void Dijkstra(int start)
    {
        int kind;
        if(start==1)
            kind=1;
        else
            kind=2;
        priority_queue < node >    que;
        node s;
        s.u=start;
        s.dist=0;
        Dist[kind][start]=0;
        que.push(s);
        while(!que.empty())
        {
           s=que.top();
           que.pop();
           if(vis[s.u]==1)
            continue;
           vis[s.u]=1;
           int from=s.u;
           for(int i=0;i<Set[from].size();i++)  //找到所在集合
           {
              int j=Set[from][i]; //j代表哪个集合
              if(VISIT[j]==1)
                continue;
              VISIT[j]=1;
              int edge= tt[j]; //edge代表长度
              for(int k=0;k<G[j].size();k++)  //遍历相邻节点
               {
                  node Next;
                  int to=G[j][k];
                  if(Dist[kind][to]>Dist[kind][from]+edge  || Dist[kind][to]==-1 )
                  {
                     Dist[kind][to]=Dist[kind][from] + edge;
                     Next.dist=Dist[kind][to];
                     Next.u=to;
                     que.push(Next);
                  }
               }
           }
        }
    }
    
    void solve()
    {
        init();
        Dijkstra(1);
        init();
        Dijkstra(n);
        for(int i=1;i<=n;i++)
        {
           // cout<<Dist[1][i]<<" "<<Dist[2][i]<<endl;
            if(Dist[1][i]==-1 || Dist[2][i]==-1)
                answer[i]=-1;
            else
            answer[i]=max(Dist[1][i],Dist[2][i]);
        }
         LL MIN=-1;
         for(int i=1;i<=n;i++)
         {
             if(MIN > answer[i] || (MIN==-1) )
                MIN=answer[i];
         }
         if(MIN==-1)
            printf("Evil John
    ");
         else
         {
              printf("%I64d
    ",MIN);
              int flag=0;
              for(int i=1;i<=n;i++)
              {
                  if(MIN==answer[i])
                  {
                    if(flag==1)
                        printf(" ");
                    printf("%d",i);
                    flag=1;
                  }
              }
    
              printf("
    ");
         }
    }
    void input()
    {
            scanf("%d%d",&n,&m);
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d",&tt[i],&ss[i]);
                for(int j=1;j<=ss[i];j++)
                {
                    int input;
                    scanf("%d",&input);
                    G[i].push_back(input);
                    Set[input].push_back(i);
                }
            }
    }
    void Init()
    {
       for(int i=0;i<maxn;i++)
       {
           G[i].clear(); Set[i].clear();
       }
        memset(Dist,-1,sizeof(Dist));
    }
    int main()
    {
        //freopen("test.txt","r",stdin);
        scanf("%d",&t);
        int Case=0;
       // printf("%d
    ",inf);
       // cout<<inf<<endl;
        while(t--)
        {
            Init();
            input();
            printf("Case #%d: ",++Case);
            solve();
        }
        return 0;
    }
  • 相关阅读:
    经方膏方
    荆防柴朴汤
    温经汤治痤疮
    经方治疗带状疱疹
    用排除法诊断半表半里证
    leaflet 学习备忘
    在线数据库设计 初稿 想法简单验证
    SVG PATH 生成器
    模仿bootstrap做的 js tooltip (添加鼠标跟随功能)
    js 生成随机炫彩背景
  • 原文地址:https://www.cnblogs.com/xianbin7/p/4982156.html
Copyright © 2020-2023  润新知