PKU 1511 Invitation Cards (SPFA+邻接表)
题目链接:点击打开链接
题目需要求从原点到所有点的最短距离之和和所有点到原点的最短距离之和,在求所有点到原点最短距离的时候用到了一个技巧:即把图反向,求原点到所有其他点的最短距离,这样用一次SPFA就可以将所有点到原点的最短距离求出来了。
另外也没什么好说的,纯SPFA。另外用优化到VlogE的dijkstra貌似也能过,有空的时候再写个。
代码如下:
#include <iostream> #include <algorithm> #include <string> #include <sstream> #include <queue> using namespace std; #define MAX 1000009 #define INF 1<<30 struct ENode { int to, cost, next; } enode[MAX * 4]; int NE = 0; int OriginHead[MAX], RevHead[MAX]; int dist[MAX]; void insertEdge( int from, int to, int cost ) { enode[NE].cost = cost; enode[NE].to = to; enode[NE].next = OriginHead[from]; OriginHead[from] = NE++; enode[NE].cost = cost; enode[NE].to = from; enode[NE].next = RevHead[to]; RevHead[to] = NE++; } void initDist( int n ) { for (int i=0; i<=n; i++) dist[i] = INF; dist[1] = 0; } int inQueue[MAX]; queue<int> Q; void SPFA( int *Head ) { inQueue[1] = 1; Q.push(1); while ( ! Q.empty() ) { int q = Q.front(); Q.pop(); inQueue[q] = 0; for ( int i=Head[q]; i!=-1; i=enode[i].next ) { int e = enode[i].to; if ( dist[q] + enode[i].cost < dist[e] ) { dist[e] = dist[q] + enode[i].cost; if ( !inQueue[e] ) { inQueue[e] = 1; Q.push( e ); } } } } } long long getTotal( int n ) { long long ret = 0; for (int i=2; i<=n; i++) ret += dist[i]; return ret; } int main( ) { //cout << (int)(1<<30) << endl; int T; cin >> T; while( T-- ) { int n, m; scanf("%d%d", &n, &m); memset( OriginHead, -1, sizeof(OriginHead) ); memset( RevHead, -1, sizeof(RevHead) ); NE = 0; for (int i=0; i<m; i++) { int from, to, cost; scanf( "%d%d%d", &from, &to, &cost ); insertEdge( from, to, cost ); } initDist( n ); memset( inQueue, 0, sizeof(inQueue) ); SPFA( OriginHead ); long long int ans = 0; ans += getTotal( n ); //cout << ans << endl; initDist( n ); memset( inQueue, 0, sizeof(inQueue) ); SPFA( RevHead ); ans += getTotal( n ); cout << ans << endl; } return 0; }