POJ - 1511 Invitation Cards 往返最短路之和正向反向存边

题目链接
题意
给P个点Q条边的图,求所有点到1这个点的往返最短路之和。
思路
正向和反向分别存边,跑两遍dijkstra就可以了。

#include <iostream>
#include <cstdio>
#include <queue>
#include <string.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
#define pr pair<int, int>

const int MAXN = 1e6 + 7;
int head[2][MAXN], to[2][MAXN], nex[2][MAXN], n, m;
int edge[2][MAXN], cnt1, cnt2;
int d[2][MAXN];
bool final[MAXN];
int s, e;

void add(int x, int y, int val, int op)
{
    if(op == 1) {
        to[op][++cnt2] = y;
        edge[op][cnt2] = val;
        nex[op][cnt2] = head[op][x];
        head[op][x] = cnt2;
        return;
    }
	to[op][++cnt1] = y;
	edge[op][cnt1] = val;
	nex[op][cnt1] = head[op][x];
	head[op][x] = cnt1;
}
void dijkstra(int op)
{
	memset(final, 0, sizeof(final));
	for (int i = 1; i <= n; i++) d[op][i] = INF;
	priority_queue<pr, vector<pr>, greater<pr> > q;
	q.push(make_pair(0, s));//first是length,second是顶点
	d[op][s] = 0;
	while (!q.empty())
	{
		int u = q.top().second;
		q.pop();
		final[u] = true;
		for (int i = head[op][u]; ~i; i = nex[op][i])
		{
			int v = to[op][i];
			int len = edge[op][i];
			if(!final[v] && d[op][v] > d[op][u] + len)
			{
				d[op][v] = d[op][u] + len;
				q.push(make_pair(d[op][v], v));
			}
		}
	}
}
int main()
{
	int t;
	cin >> t;
	while (t--) {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) head[0][i] = head[1][i] = -1;
        cnt1 = 0, cnt2 = 0;
        for (int i = 1; i <= m; i++) {
            int x, y, z;
            scanf("%d%d%d", &x, &y, &z);
            add(x, y, z, 1); add(y, x, z, 0);//1 正向边,0 反向边
        }
        s = 1;
        dijkstra(1);
        dijkstra(0);
        ll ans = 0;
        for (int i = 2; i <= n; i++) {
            ans += d[0][i] + d[1][i];
        }
        cout << ans << endl;
	}
}

发布了26 篇原创文章 · 获赞 2 · 访问量 412

猜你喜欢

转载自blog.csdn.net/D_Bamboo_/article/details/103545999