大意:给你一个源点,让你从这里派发n个学生去其余的n-1个站点去邀请人们去CSS,然后再返回CSS,使得总的cost最小。

 

思路:

(1)过去的时候:求一次最短路,将所有的d[i]相加。

(2)回来的时候:我开始想把SPFA所有的点,然后相加,估计会超时。由于是有向边,可以用到一个巧妙的转移的方法,我们将有向边反向,由于题目保证所有的点均可到达,所以SPFA源点,然后相加可得结果。

 

CODE:

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

const int SIZE = 1000001;
const int INF = 0x3f3f3f3f;
int u[2*SIZE], v[2*SIZE], w[2*SIZE], next[2*SIZE];
int s_u[2*SIZE], s_v[2*SIZE], s_w[2*SIZE];
int first[SIZE], d[SIZE];
int n, m, cnt;

void init()
{
    memset(u, 0sizeof(u));
    memset(v, 0sizeof(v));
    memset(w, INF, sizeof(w));
    memset(d, 0sizeof(d));
    memset(next, 0sizeof(next));
    memset(first, -1sizeof(first));
    cnt = 0;
}

void spfa(int src)
{
    queue<int> q;
    bool inq[SIZE] = {0};
    for(int i = 1; i <= n; i++) d[i] = (i == src)? 0:INF;
    q.push(src);
    while(!q.empty())
    {
        int x = q.front(); q.pop();
        inq[x] = 0;
        for(int e = first[x]; e!=-1; e = next[e]) if(d[v[e]] > d[x]+w[e])
        {
            d[v[e]] = d[x] + w[e];
            if(!inq[v[e]])
            {
                inq[v[e]] = 1;
                q.push(v[e]);
            }
        }
    }
}

void read_graph(int u1, int v1, int w1)
{
    u[cnt] = u1; v[cnt] = v1; w[cnt] = w1;
    next[cnt] = first[u[cnt]];
    first[u[cnt]] = cnt;
    cnt++;
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int ans = 0;
        init();
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= m; i++)    scanf("%d%d%d", &s_u[i], &s_v[i], &s_w[i]);
        for(int i = 1; i <= m; i++) read_graph(s_u[i], s_v[i], s_w[i]);
        spfa(1);
        for(int i = 1; i <= n; i++) ans += d[i];
        init();
        for(int i = 1; i <= m; i++) read_graph(s_v[i], s_u[i], s_w[i]);
        spfa(1);
        for(int i = 1; i <= n; i++) ans += d[i];
        printf("%d\n", ans);
    }
    return 0;
}

 

 

posted on 2012-09-14 20:52  有间博客  阅读(654)  评论(0编辑  收藏  举报