zoukankan      html  css  js  c++  java
  • HDU 4725 最短路

    /*

    *好险 968ms飘过。。。。。。。。。

    *说说我的感受,刚开始就直接敲堆优化的dij...发现直接就TLE了,改了好多种建边的方法依然是超时,之后才想到这种方法:

    *给每层建两个结点,分别标记为 n+2*i-1 和 n +2*i 。然后每个结点到它所在层结点的费用为0,第i层到第i+1层的费用为 C。

    *当然由于是双向边,要保证相邻两层的结点都是互相可达的。

    */


     1 #include<stdio.h>
     2 
     3 #include<string.h>
     4 #include<queue>
     5 #include<vector>
     6 using namespace std;
     7 #define min(x,y) (x<y?x:y)
     8 #define max(x,y) (x>y?x:y)
     9 #define max_n 100010*3
    10 #define inf 0x3f3f3f3f
    11 
    12 int n,m,c;
    13 struct Edge{
    14     int to,dist;
    15     Edge(int t,int d):to(t),dist(d){}
    16 };
    17 struct node{
    18     int d,u;
    19     node(int dd,int uu):d(dd),u(uu){}
    20     bool operator < (const node& tmp)const{
    21         return d>tmp.d;
    22     }
    23 };
    24 vector<int> next[max_n];//每个结点出发的边编号
    25 vector<Edge> edges;     //边列表
    26 bool done[max_n];       //是否已永久标记
    27 int d[max_n];           //1到各个点的距离
    28 
    29 void init(int n){       
    30     for(int i=1;i<=n*3;i++){
    31         next[i].clear();//清空临界表
    32     }
    33     edges.clear();//清空边表
    34 }
    35 
    36 void add_edge(int from,int to,int dist){
    37     //无向图需两次加边
    38     edges.push_back(Edge(to,dist));
    39     int count=edges.size();
    40     next[from].push_back(count-1);
    41 }
    42 
    43 void dij(){
    44     memset(d,0x3f,sizeof(d));
    45     d[1]=0;
    46     memset(done,false,sizeof(done));
    47     priority_queue<node> q;
    48     q.push(node(0,1));
    49     while(!q.empty()){
    50         node x=q.top(); q.pop();
    51         int u=x.u;
    52         if(done[u]){
    53             continue;
    54         }
    55         done[u]=true;
    56         for(int i=0;i<next[u].size();i++){
    57             Edge& e=edges[next[u][i]];
    58             if(!done[e.to]&&d[e.to]>d[u]+e.dist){
    59                 d[e.to]=d[u]+e.dist;
    60                 q.push(node(d[e.to],e.to));
    61             }    
    62         }
    63     }
    64 }
    65 
    66 int main(){
    67     int T;
    68     scanf("%d",&T);
    69     for(int t=1;t<=T;t++){
    70         scanf("%d%d%d",&n,&m,&c);
    71         init(n);
    72         for(int i=1;i<=n;i++){
    73             int u;
    74             scanf("%d",&u);
    75             add_edge(i,n+2*u-1,0);
    76             add_edge(n+2*u,i,0);
    77         }
    78         for(int i=1;i<n;i++){
    79             add_edge(n+2*i-1,n+2*(i+1),c);
    80             add_edge(n+2*(i+1)-1,n+2*i,c);
    81         }
    82         for(int i=1;i<=m;i++){
    83             int u,v,w;
    84             scanf("%d%d%d",&u,&v,&w);
    85             add_edge(u,v,w);
    86             add_edge(v,u,w);
    87         }
    88         dij();
    89         printf("Case #%d: ",t);
    90         if(d[n]==inf){
    91             puts("-1");
    92         }
    93         else{
    94             printf("%d
    ",d[n]);
    95         }
    96     }
    97 }
  • 相关阅读:
    C#打造51CTO自动签到服务领取无忧币之开篇
    Windows8开发实战之文本布局
    设计模式之抽像工厂
    PDM只显示表名称不显示列表名称
    JS 判断中英文字符长度
    C#操作剪贴板实现复制粘贴
    Chrome控制台设置浏览器Cookie
    通过Mysql查询分析器 建库建表语句
    推荐两个VS开发工具插件
    C#经典机试题(猫叫)
  • 原文地址:https://www.cnblogs.com/Stomach-ache/p/3703193.html
Copyright © 2011-2022 走看看