• HDU 4725 建图


    http://acm.hdu.edu.cn/showproblem.php?pid=4725

    The Shortest Path in Nya Graph

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


    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
    一开始无脑暴力建 N1*N2的图,后来超时后才发现,如果层数稀疏,点数密集的话建的边数上亿,肯定要超时的,我们想办法巧妙地建图。
    把每一层看做是一个点,通过点->层->点的连接从而实现层与层的连接,可以少建许多边,但我第一次没考虑周到,让点与对应的层建立了双向边,这是致命的,,
    因为每一层的点之间距离并非是0,这样构图的话每一层得点相互之间都能0距离显然是错误的。
    考虑建单向边,让每一层向层上的点建一条0边,然后对于每个点,向与其相邻且存在的层建立一条权值为C的边,这样就符合了题意。
    spfa和dij都写了感觉复杂度差不多,但是第一次建图错误时spfa提示TLE,dij返回WA不知道是否说明dij快点- -反正二者AC的时间差不大多
      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<queue>
      5 using namespace std;
      6 #define inf 0x3f3f3f3f
      7 inline int read()
      8 {
      9     int r=0;  char c=getchar();
     10     while(!isdigit(c)) c=getchar();
     11     while(isdigit(c)) {r=r*10+c-'0';c=getchar();}
     12     return r;
     13 }
     14 struct Edge
     15 {
     16     int to,w,next;
     17 }e[600005];
     18 int cnt,first[200005];
     19 void add(int u,int v,int w)
     20 {
     21     e[cnt].to=v;
     22     e[cnt].w=w;
     23     e[cnt].next=first[u];
     24     first[u]=cnt++;
     25 }
     26 struct node
     27 {
     28     int u,w;
     29     bool operator<(const node &x)const{
     30     return w>x.w;
     31     }
     32 };
     33 int d[200005];
     34 int dij(int N)
     35 {
     36     bool vis[200005];
     37     priority_queue<node>Q;
     38     memset(vis,0,sizeof(vis));
     39     memset(d,inf,sizeof(d));
     40     d[1]=0;
     41     Q.push(node{1,0});
     42     while(!Q.empty()){
     43         node t1=Q.top();Q.pop();
     44         int u=t1.u;
     45         if(vis[u]) continue;
     46         vis[u]=1;
     47         if(u==N) break;
     48         for(int i=first[u];i+1;i=e[i].next){
     49             Edge x=e[i];
     50             if(!vis[x.to]&&d[x.to]>d[u]+x.w){
     51                 d[x.to]=d[u]+x.w;
     52                 Q.push(node{x.to,d[x.to]});
     53             }
     54         }
     55     }
     56     return d[N]==inf?-1:d[N];
     57 }
     58 int spfa(int N)
     59 {
     60     bool vis[200005];
     61     queue<int>Q;
     62     memset(vis,0,sizeof(vis));
     63     memset(d,inf,sizeof(d));
     64     Q.push(1);
     65     vis[1]=1;
     66     d[1]=0;
     67     while(!Q.empty()){
     68         int u=Q.front(); Q.pop();
     69         vis[u]=0;
     70         for(int i=first[u];i+1;i=e[i].next){
     71             Edge x=e[i];
     72             if(d[x.to]>d[u]+x.w){
     73                 d[x.to]=d[u]+x.w;
     74                 if(!vis[x.to]){
     75                     Q.push(x.to);
     76                 }
     77             }
     78         }
     79     }
     80     return d[N]==inf?-1:d[N];
     81 }
     82 int main()
     83 {
     84     //ios::sync_with_stdio(false);
     85     int T,N,M,C,i,j,k=0;
     86     int u,v,w,x[100005];
     87     bool layer[100005];
     88    #ifndef ONLINE_JUDGE
     89    freopen("in.txt","r",stdin);
     90    #endif
     91     T=read();
     92     for(int cas=1;cas<=T;++cas)
     93     {
     94         cnt=0;
     95         memset(first,-1,sizeof(first));
     96         memset(layer,0,sizeof(layer));
     97         cin>>N>>M>>C;
     98         for(i=1;i<=N;++i)
     99         {
    100             x[i]=read();
    101             layer[x[i]]=1;
    102         }
    103        for(i=1;i<=N;++i)
    104         {
    105             add(x[i]+N,i,0);
    106             add(i,x[i]+N,0);
    107             if(x[i]>1&&layer[x[i]-1])
    108                 add(i,x[i]+N-1,C);
    109             if(x[i]<N&&layer[x[i]+1])
    110                 add(i,x[i]+N+1,C);
    111         }
    112         while(M--){
    113         scanf("%d%d%d",&u,&v,&w);
    114             add(u,v,w);
    115             add(v,u,w);
    116         }
    117         printf("Case #%d: %d
    ",cas,dij(N)/*spfa(N)*/);
    118     }
    119     return 0;
    120 }
  • 相关阅读:
    【笔记】机器学习
    【笔记】机器学习
    【NLP】暑假课作业3
    【NLP】暑假课作业1
    【笔记】机器学习
    【转】谈谈我对攻读计算机研究生的看法
    Android学习笔记-事件处理
    精读《C++ primer》学习笔记(第四至六章)
    那些年,当我还是个小白
    精读《C++ primer》学习笔记(第一至三章)
  • 原文地址:https://www.cnblogs.com/zzqc/p/7360507.html
Copyright © 2020-2023  润新知