• HDU4725 SPFA (最短路+层级建图)




    问题描述
    这是一个非常容易的问题,你的任务只是计算el camino mas corto en un grafico,而且只是单独干草阙cambiar un poco el algoritmo。如果你不理解这一段的话,那就继续吧。

    Nya图是具有“层”的无向图。图中的每个节点都属于一个层,总共有N个节点。
    您可以从层x中的任何节点移动到层x + 1中的任何节点,成本为C,因为道路是双向的,从层x + 1移动到层x也允许具有相同的成本。
    此外,还有M个额外边缘,每个边缘连接一对节点u和v,成本为w。
    帮助我们计算从节点1到节点N的最短路径。

    输入
    第一行的数字为T(T <= 20),表示测试用例的数量。
    对于每个测试用例,第一行有三个数字N,M(0 <= N,M <= 105)和C(1 <= C <= 103),这是节点数,额外边数和成本在相邻层之间移动。
    第二行有N个数字li(1 <= li <= N),这是第i个节点所属的层。
    然后得到N行,每行有3个数字,u,v(1 <= u,v <= N,u <> v)和w(1 <= w <= 104),这意味着有一条额外的边,连接一个节点u和v对,成本为w。

    产量
    对于测试用例X,首先输出“Case #X:”,然后输出从节点1移动到节点N的最小成本。
    如果没有解决方案,则输出-1。

    样本输入
    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

    样本输出
    案例#1:2
    案例#2:3




    如果是每个点向比他层级小一或大一的点连边的话,复杂度为n××2,所以说每层抽象一个点,每层的抽象出来的点先此层的点连边,以此就避免的枚举每个点的层数

    坑点: 同层之间的点不连通

      1 #include <cstdio>
      2 #include <cmath>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <climits>
      6 #include <ctype.h>
      7 #include <queue>
      8 #include <stack>
      9 #include <vector>
     10 #include <deque>
     11 #include <set>
     12 #include <map>
     13 #include <iostream>
     14 #include <algorithm>
     15 using namespace std;
     16 #define pi acos(-1.0)
     17 #define INF 0x3f3f3f3f
     18 #define N 200017
     19 int n, m, k, c;
     20 int Edgehead[N], dis[N];
     21 int vv[N], lay[N];
     22 struct
     23 {
     24     int v,w,next;
     25 } Edge[20*N];
     26 bool vis[N];
     27 int cont[N];
     28 
     29 void init()
     30 {
     31     memset(Edgehead,0,sizeof(Edgehead));
     32     memset(vv,0,sizeof(vv));
     33 }
     34 
     35 void Addedge(int u,int v,int w)
     36 {
     37     Edge[k].next = Edgehead[u];
     38     Edge[k].w = w;
     39     Edge[k].v = v;
     40     Edgehead[u] = k++;
     41 }
     42 int SPFA( int start)
     43 {
     44     queue<int>Q;
     45     while(!Q.empty()) Q.pop();
     46     for(int i = 1 ; i <= N ; i++ )
     47         dis[i] = INF;
     48     dis[start] = 0;
     49     //++cont[start];
     50     memset(vis,false,sizeof(vis));
     51     vis[start] = 1;
     52     Q.push(start);
     53     while(!Q.empty())//直到队列为空
     54     {
     55         int u = Q.front();
     56         Q.pop();
     57         vis[u] = false;
     58         for(int i = Edgehead[u] ; i!=-1 ; i = Edge[i].next)//注意
     59         {
     60             int v = Edge[i].v;
     61             int w = Edge[i].w;
     62             if(dis[v] > dis[u] + w)
     63             {
     64                 dis[v] = dis[u]+w;
     65                 if( !vis[v] )//防止出现环,也就是进队列重复了
     66                 {
     67                     Q.push(v);
     68                     vis[v] = true;
     69                 }
     70                 //if(++cont[v] > n)//有负环
     71                 //   return -1;
     72             }
     73         }
     74     }
     75     return dis[n];
     76 }
     77 int main()
     78 {
     79     int u, v, w;
     80     int t;
     81     int cas = 0;
     82     scanf("%d",&t);
     83     while(t--)
     84     {
     85         init();
     86         scanf("%d%d%d",&n,&m,&c);
     87         k = 1;
     88         memset(Edgehead,-1,sizeof(Edgehead));
     89 
     90         for(int i = 1; i <= n; i++)
     91         {
     92             scanf("%d",&u);//i 在第u层
     93             lay[i] = u;
     94             vv[u] = 1;
     95         }
     96 
     97         for(int i = 1; i < n; i++)
     98         {
     99             if(vv[i] && vv[i+1])  //两层都出现过点相邻层才建边
    100             {
    101                 Addedge(n+i,n+i+1,c);
    102                 Addedge(n+i+1,n+i,c);
    103             }
    104         }
    105 
    106         for(int i = 1; i <= n; i++)  //层到点建边  点到相邻层建边
    107         {
    108             Addedge(n+lay[i],i,0);
    109 
    110 
    111             if(lay[i] > 1)
    112                 Addedge(i,n+lay[i]-1,c);
    113             if(lay[i] < n)
    114                 Addedge(i,n+lay[i]+1,c);
    115                 
    116 
    117         }
    118 
    119         for(int i = 1 ; i <= m ; i++ )
    120         {
    121             scanf("%d%d%d",&u,&v,&w);
    122             Addedge(u,v,w);//双向链表
    123             Addedge(v,u,w);//双向链表
    124         }
    125         int s = SPFA(1);//从点1开始寻找最短路
    126         if(s == INF)
    127         {
    128             s = -1;
    129         }
    130         printf("Case #%d: %d
    ",++cas,s);
    131     }
    132     return 0;
    133 }
  • 相关阅读:
    夜半随笔
    VC6.0 工程转到VS2008一些问题
    没有找到MSVCR90.dll,因此这个应用程序未能启动,重新安装应用程序可解决
    开源中国
    保存桌面图标的次序吧
    2008下,错误:fatal error C1853
    生成成功,调试时出现错误导致中断Unhandled exception at 0x41cd7fb0 in webcam.exe: 0xC0000005: Access violatio
    opencv安装可能没注意的细节
    error PRJ0003 : 生成“cl.exe”时出错
    wince对话框添加菜单
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/10289470.html
Copyright © 2020-2023  润新知