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 }
原文地址:https://www.cnblogs.com/Stomach-ache/p/3703193.html