zoukankan      html  css  js  c++  java
  • The Shortest Path in Nya Graph

    The Shortest Path in Nya Graph

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 6492    Accepted Submission(s): 1469


    Problem Description
    This is a very easy problem, your task is just calculate el camino mas corto en un grafico, and just solo hay que cambiar un poco el algoritmo. If you do not understand a word of this paragraph, just move on.
    The Nya graph is an undirected graph with "layers". Each node in the graph belongs to a layer, there are N nodes in total.
    You can move from any node in layer x to any node in layer x + 1, with cost C, since the roads are bi-directional, moving from layer x + 1 to layer x is also allowed with the same cost.
    Besides, there are M extra edges, each connecting a pair of node u and v, with cost w.
    Help us calculate the shortest path from node 1 to node N.
     
    Input
    The first line has a number T (T <= 20) , indicating the number of test cases.
    For each test case, first line has three numbers N, M (0 <= N, M <= 105) and C(1 <= C <= 103), which is the number of nodes, the number of extra edges and cost of moving between adjacent layers.
    The second line has N numbers li (1 <= li <= N), which is the layer of ith node belong to.
    Then come N lines each with 3 numbers, u, v (1 <= u, v < =N, u <> v) and w (1 <= w <= 104), which means there is an extra edge, connecting a pair of node u and v, with cost w.
     
    Output
    For test case X, output "Case #X: " first, then output the minimum cost moving from node 1 to node N.
    If there are no solutions, output -1.
     
    Sample Input
    2 3 3 3 1 3 2 1 2 1 2 3 1 1 3 3 3 3 3 1 3 2 1 2 2 2 3 2 1 3 4
     
    Sample Output
    Case #1: 2 Case #2: 3
    Source
     
    Recommend
    zhuyuanchen520   |   We have carefully selected several similar problems for you:  6032 6031 6030 6029 6028 
    【思路】
    拆点+spfa
    将每一层拆成两个点,至于为什么是两个点,等等下面说QUQ
    我们将设已经将每一层拆成两个点。
    现在我们将点与点,层与点,点与点之间连线。
    可能有点晕~上图.......
    我画图画晕了....下面是个假图,明天补orz
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define MAXX 200017
    #define inf 0x3f3f3f3f
    struct Edge
    {
        int x,y,z,nxt;
        Edge(int x=0,int y=0,int z=0,int nxt=0):
            x(x),y(y),z(z),nxt(nxt){}
    }edge[MAXX];
    /*inline int read()
    {
        int f=1,x=0;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return f*x;
    }*/
    int head[MAXX],sumedge,n,m,vs,t,x,cnt,dis[MAXX],vc,u,v,w,vis[MAXX];
     void add(int x,int y,int z)
    {
        //edge[++sumedge]=Edge(x,y,z,head[x]);
        edge[++sumedge].x=x;edge[sumedge].y=y;edge[sumedge].z=z;edge[sumedge].nxt=head[x];
        head[x]=sumedge;
    }
    
    /*inline void spfa()
    {
        dis[1]=0;vis[1]=1;
        deque <int>q;q.push_back(1);
        while(q.size())
        {
            int now=q.front();q.pop_front();
            vis[now]=0;
            for(int i=head[now];i;i=edge[i].nxt)
            {
                int to=edge[i].y;
                if(dis[to]>dis[now]+edge[i].z)
                {
                    dis[to]=dis[now]+edge[i].z;
                    if(!vis[to])
                    {
                        vis[to]=1;
                        if(q.size()&&dis[to]<dis[q.front()])
                        q.push_front(to);
                        else q.push_back(to);
                    }
                }
            }
        }
    }*/
     void spfa()
    {
        for(int i=1;i<=n;i++)dis[i]=0x3f;
        queue <int> q;
        dis[1]=0;vis[1]=1;
        q.push(1); 
        while(!q.empty())
        {
            int now=q.front();q.pop();
            vis[now]=0;
            for(int i=head[now];i;i=edge[i].nxt)
            {
                int to=edge[i].y;
                if(dis[to]>dis[now]+edge[i].z)
                {
                    dis[to]=dis[now]+edge[i].z;
                    if(!vis[to])
                    {
                        vis[to]=1;
                        q.push(to); 
                    }
                }
            }
        }
    }
    int main()
    {
        scanf("%d",&t);
        while(t--)
        {
        //    init();
    //    memset(dis,0x3f,sizeof(dis));
        memset(head,0,sizeof(head));
        memset(vis,0,sizeof(vis)); 
        sumedge=0;
    //    n=read();m=read();vc=read();//出i+n;入i+2*n; 
        scanf("%d%d%d",&n,&m,&vc);
        for(int i=1;i<=n;i++)
        {
            if(i!=n)
            {
            add(i+n,i+2*n+1,vc);
            add(i+n+1,i+2*n,vc);
            }
    //        x=read();
        scanf("%d",&x);
            add(i,n+x,0);
            add(x+2*n,i,0);
        }
        for(int i=1;i<=m;i++)
        {
        //    u=read();v=read();w=read();
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);add(v,u,w);
        } 
            spfa();
            if(dis[n]==inf)printf("Case #%d: -1
    ",++cnt);
            else printf("Case #%d: %d
    ",++cnt,dis[n]);
        }
        return 0;
    }
    #include <cstdio>  
    #include <cmath>  
    #include <cstring>  
    #include <cstdlib>  
    #include <climits>  
    #include <ctype.h>  
    #include <queue>  
    #include <stack>  
    #include <vector>  
    #include <deque>  
    #include <set>  
    #include <map>  
    #include <iostream>  
    #include <algorithm>  
    using namespace std;  
    #define pi acos(-1.0)  
    #define INF 0x3f3f3f3f  
    #define N 200017  
    int n, m, k, c;  
    int Edgehead[N], dis[N];  
    int vv[N], lay[N];  
    struct  
    {  
        int v,w,next;  
    } Edge[20*N];  
    bool vis[N];  
    int cont[N];  
      
    void init()  
    {  
        memset(Edgehead,0,sizeof(Edgehead));  
        memset(vv,0,sizeof(vv));  
    }  
      
    void Addedge(int u,int v,int w)  
    {  
        Edge[k].next = Edgehead[u];  
        Edge[k].w = w;  
        Edge[k].v = v;  
        Edgehead[u] = k++;  
    }  
    int SPFA( int start)  
    {  
        queue<int>Q;  
        while(!Q.empty()) Q.pop();  
        for(int i = 1 ; i <= N ; i++ )  
            dis[i] = INF;  
        dis[start] = 0;  
        //++cont[start];  
        memset(vis,false,sizeof(vis));  
        vis[start] = 1;  
        Q.push(start);  
        while(!Q.empty())//直到队列为空  
        {  
            int u = Q.front();  
            Q.pop();  
            vis[u] = false;  
            for(int i = Edgehead[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;  
                    if( !vis[v] )//防止出现环,也就是进队列重复了  
                    {  
                        Q.push(v);  
                        vis[v] = true;  
                    }  
                    //if(++cont[v] > n)//有负环  
                    //   return -1;  
                }  
            }  
        }  
        return dis[n];  
    }  
    int main()  
    {  
        int u, v, w;  
        int t;  
        int cas = 0;  
        scanf("%d",&t);  
        while(t--)  
        {  
            init();  
            scanf("%d%d%d",&n,&m,&c);  
            k = 1;  
            memset(Edgehead,-1,sizeof(Edgehead));  
              
            for(int i = 1; i <= n; i++)  
            {  
                scanf("%d",&u);//i 在第u层  
                lay[i] = u;  
                vv[u] = 1;  
            }  
              
            for(int i = 1; i < n; i++)  
            {  
                if(vv[i] && vv[i+1])  //两层都出现过点相邻层才建边  
                {  
                    Addedge(n+i,n+i+1,c);  
                    Addedge(n+i+1,n+i,c);  
                }  
            }  
      
            for(int i = 1; i <= n; i++)  //层到点建边  点到相邻层建边  
            {  
                Addedge(n+lay[i],i,0);  
                if(lay[i] > 1)  
                    Addedge(i,n+lay[i]-1,c);  
                if(lay[i] < n)  
                    Addedge(i,n+lay[i]+1,c);  
            }  
      
            for(int i = 1 ; i <= m ; i++ )  
            {  
                scanf("%d%d%d",&u,&v,&w);  
                Addedge(u,v,w);//双向链表  
                Addedge(v,u,w);//双向链表  
            }  
            int s = SPFA(1);//从点1开始寻找最短路  
            if(s == INF)  
            {  
                s = -1;  
            }  
            printf("Case #%d: %d
    ",++cas,s);  
        }  
        return 0;  
    }  
  • 相关阅读:
    Running APP 使用说明
    Android 控件八 WebView 控件
    Android 控件七 ImageView 控件
    Android 控件六 CheckBox 控件
    Android 控件五 RadioButton 控件
    Android 控件四 EditText 控件
    Android 控件三 TextView 控件实现 Button
    Android 控件二 Button
    Android 基础控件演示实例
    Android 控件一 TextView
  • 原文地址:https://www.cnblogs.com/zzyh/p/6947336.html
Copyright © 2011-2022 走看看