最短路 || POJ 1511 Invitation Cards

已知图中从一点到另一点的距离,从1号点到另一点再从这一点返回1号点,求去到所有点的距离之和最小值
*解法:正着反着分别建图,把到每个点的距离加起来
spfa跑完之后dist数组就是从起点到每一点的最短距离
get反着建图这种技能
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
#define SZ 1000005
#define INF 1e18+10
long long dist[SZ], tmp[SZ], dis = 0;
int head[SZ], nxt[SZ], tot = 0;
int x[SZ], y[SZ];
long long z[SZ];
int use[SZ];
struct edge
{
    int t;
    long long d;
}l[SZ];
void build(int f, int t, long long d)
{
    l[++tot] = (edge){t, d};
    nxt[tot] = head[f];
    head[f] = tot;
}
queue<int> q;
int p, qq;
void spfa()
{
    for(int i = 1; i <= p; i++) dist[i] = INF, use[i] = 0;
    use[1] = 1, dist[1] = 0;
    q.push(1);
    while(q.size())
    {
        int u = q.front();
        q.pop();
        use[u] = 0;
        for(int i = head[u]; i; i = nxt[i])
        {
            int v = l[i].t;
            if(dist[v] > dist[u] + l[i].d)
            {
                dist[v] = dist[u] + l[i].d;
                if(!use[v])
                    use[v] = 1, q.push(v);
            }
        }
    }
}
int main()
{
    int T, s = 1;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d %d", &p, &qq);
        dis = 0;
        tot = 0;
        for(int i = 0; i < qq; i++) head[i] = nxt[i] = use[i] = 0;
        for(int i = 0; i < qq; i++)
        {
            scanf("%d %d %lld", &x[i], &y[i], &z[i]);
            build(x[i], y[i], z[i]);
        }
        spfa();
        for(int i = 1; i <= p; i++) tmp[i] = dist[i];
        tot = 0;
        for(int i = 0; i < qq; i++)
            head[i] = nxt[i] = use[i] = 0;
        for(int i = 0; i < qq; i++)
            build(y[i], x[i], z[i]);
        spfa();
        for(int i = 1; i <= p; i++)
            dis = dis + tmp[i] + dist[i];
        printf("%lld\n", dis);
    }
    return 0;
}

 

posted @ 2018-02-02 13:39  舒羽倾  阅读(125)  评论(0)    收藏  举报