POJ-1511 Invitation Cards---Dijkstra+队列优化+前向星正向反向存图

题目链接:

https://vjudge.net/problem/POJ-1511

题目大意:

给定节点数n,和边数m,边是单向边.

问从1节点出发到2,3,...n 这些节点路程和从从这些节点回来到节点1的路程和最小值。

n,m不超过1e6

思路:

POJ-3268是一样的,大概思路都是正向从源点求最短路,然后把图反向,再从源点求最短路,但是这道题是它的进阶版本,由于点数过多,不可以用邻接矩阵存图,这里用前向星存图,同时存下两张图,一张正向,一张反向。Dijkstra算法用队列优化,注意用long long存答案和dist最短路距离。其他的就是模板题了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<queue>
 7 #include<stack>
 8 #include<map>
 9 #include<set>
10 #include<sstream>
11 using namespace std;
12 typedef long long ll;
13 const int maxn = 1e6 + 10;
14 const int INF = 1e9 + 7;
15 int T, n, m, cases;
16 struct edge
17 {
18     int next, u, v, w;
19 };
20 edge a[2][maxn];//a[0][]存正边 a[1][]存反边
21 ll d[maxn];
22 int head[2][maxn];
23 bool v[maxn];
24 void init()
25 {
26     memset(head, -1, sizeof(head));
27 }
28 struct HeapNode
29 {
30     int d, u;//d是距离,u是顶点
31     HeapNode(){}
32     HeapNode(int d, int u):d(d), u(u){}
33     bool operator <(const HeapNode & a)const
34     {
35         return d > a.d;
36     }
37 };
38 void dijkstra(int cnt)
39 {
40     priority_queue<HeapNode>q;
41     for(int i = 0; i <= n; i++)d[i] = INF;
42     d[1] = 0;
43     memset(v, 0, sizeof(v));
44     q.push(HeapNode(0, 1));
45     while(!q.empty())
46     {
47         HeapNode now = q.top();
48         q.pop();
49         int u = now.u;
50         if(v[u])continue;
51         v[u] = 1;//标记
52         for(int i = head[cnt][u]; ~i; i = a[cnt][i].next)
53         {
54             edge& e = a[cnt][i];
55             int v = e.v, w = e.w;
56             if(d[v] > d[u] + w)
57             {
58                 d[v] = d[u] + w;
59                 q.push(HeapNode(d[v], v));
60             }
61         }
62     }
63 }
64 int main()
65 {
66     scanf("%d", &T);
67     while(T--)
68     {
69         init();
70         scanf("%d%d", &n, &m);
71         int u, v, w;
72         for(int i = 1; i <= m; i++)
73         {
74             scanf("%d%d%d", &u, &v, &w);
75             //正向存边
76             a[0][i].u = u;
77             a[0][i].v = v;
78             a[0][i].w = w;
79             a[0][i].next = head[0][u];
80             head[0][u] = i;
81             //反向存边
82             a[1][i].u = v;
83             a[1][i].v = u;
84             a[1][i].w = w;
85             a[1][i].next = head[1][v];
86             head[1][v] = i;
87         }
88         ll ans = 0;
89         dijkstra(0);
90         for(int i = 1; i <= n; i++)ans += d[i];
91         dijkstra(1);
92         for(int i = 1; i <= n; i++)ans += d[i];
93         cout<<ans<<endl;
94     }
95     return 0;
96 }

 

posted @ 2018-04-08 00:12  _努力努力再努力x  阅读(122)  评论(0编辑  收藏  举报