zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    UVa 1354 天平难题 (枚举二叉树)
    广西邀请赛总结
    UVa 12118 检查员的难题 (dfs判连通, 构造欧拉通路)
    UVA
    Uva 127 "Accordian" Patience (模拟)
    UVA 10539 Almost Prime Numbers( 素数因子)
    HDU 1272 小希的迷宫(并查集)
    HDU 1213 How Many Tables (并查集)
    POJ 2236 Wireless Network(并查集)
    HDU 1233 还是畅通工程 ( Kruskal或Prim)
  • 原文地址:https://www.cnblogs.com/xianbin7/p/4982156.html
Copyright © 2011-2022 走看看