HDU 6166 Spfa

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6166

题意:
给出一个n个点的有向图。然后给你k个点,求这k个点任意两点之间的最短路的最小值。
思路:
以这k个点为起点,维护每个点的最短路和次短路,并且,次短路的祖先不能是本身。

先给几组样例:

5
5 6
1 2 100
2 5 100
5 1 100
3 2 100
2 4 1
4 3 1
2
1 3

5 6
1 2 100
2 5 100
5 1 100
3 2 100
2 4 1
4 3 1
2
1 3

4 5
1 3 1
3 1 1
1 2 1000
2 4 1
4 2 1
2
1 2

3 4
1 2 100
2 3 50
1 3 1
3 1 1
2
1 2

5 6
1 2 1
2 3 3
3 1 3
2 5 1
2 4 2
4 3 1
3
1 3 5

Case #1: 102
Case #1: 102
Case #3: 1000
Case #4: 51
Case #5: 2

 

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL INF = 1e15;
const int maxn = 1e5 + 15;
int T, N, M, k;
queue<int>que;
struct Edge
{
    int to, next, len;
    Edge() {}
    Edge(int to, int next, int len): to(to), next(next), len(len) {}
} E[maxn * 4];
int head[maxn], tot;
void initEdge()
{
    for(int i = 1; i <= N; i++) head[i] = -1;
    tot = 0;
}
void addEdge(int u, int v, int len)
{
    E[tot] = Edge(v, head[u], len);
    head[u] = tot++;
}
LL dis[maxn][2];
int ant[maxn][2];
bool in[maxn], qr[maxn];
int main ()
{
    int ic = 0;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d %d", &N, &M);
        initEdge();
        for(int i = 1; i <= M; i++)
        {
            int u, v, len;
            scanf("%d %d %d", &u, &v, &len);
            addEdge(u, v, len);
        }
        for(int i = 1; i <= N; i++)//init
        {
            dis[i][0] = dis[i][1] = INF;
            ant[i][0] = ant[i][1] = -1;
            in[i] = qr[i] = false;
        }
        queue<int>que;
        scanf("%d", &k);
        for(int i = 1; i <= k; i++)
        {
            int v;
            scanf("%d", &v);
            dis[v][0] = 0;
            ant[v][0] = v;
            que.push(v), qr[v] = in[v] = true;
        }
        while(!que.empty())
        {
            int u = que.front();
            in[u] = false,que.pop();
            for(int k = head[u]; ~k; k = E[k].next)
            {
                int v = E[k].to;
                LL len = (LL)E[k].len + dis[u][0];
                bool update = false;
                if(len < dis[v][0])
                {
                    dis[v][0] = len;
                    ant[v][0] = ant[u][0];
                    update = true;
                }
                else if (len < dis[v][1] && ant[u][0] != v)
                {
                    dis[v][1] = len;
                    ant[v][1] = ant[u][0];
                    update = true;
                }
                len = (LL)E[k].len + dis[u][1];
                if (len < dis[v][1] && ant[u][1] != v)
                {
                    dis[v][1] = len;
                    ant[v][1] = ant[u][1];
                    update = true;
                }
                if(update&&!in[v])
                {
                    que.push(v);
                    in[v] = true;
                }
            }
        }
        LL ans = INF;
        for(int i=1;i<=N;i++)
            if(qr[i])   ans = min(ans,dis[i][1]);
        printf("Case #%d: %lld\n", ++ic, ans);
    }
    return 0;
}

 

posted @ 2017-08-23 16:14  _Mickey  阅读(119)  评论(0编辑  收藏  举报