【JZOJ 3470】【NOIP2013模擬聯考8】最短路(path) (spfa)

問題描述
給定一個n個點m條邊的有向圖,有k個標記點,要求從規定的起點按任意順序經過所有標記點到達規定的終點,問最短的距離是多少。
輸入
第一行5個整數n、m、k、s、t,表示點個數、邊條數、標記點個數、起點編號、終點編號。

接下來m行每行3個整數x、y、z,表示有一條從x到y的長爲z的有向邊。

接下來k行每行一個整數表示標記點編號。
輸出
輸出一個整數,表示最短距離,若沒有方案可行輸出-1。
樣例輸入
3 3 2 1 1

1 2 1

2 3 1

3 1 1

2

3
樣例輸出
3

樣例解釋

路徑爲1->2->3->1。

算法討論
這道題比較容易,我們只要先對於每個特殊點和起點終點都求一遍最短路,算出這些點之間的最短路徑長度,然後枚舉經過特殊點的順序,就能得出最優答案,注意答案會超int。

#include <cstdio>
#include <deque>
#define MAX_N 50006
#define MAX_M 100006
#define maxlongint 0xffffffff
using namespace std;
struct edge
{
    int f,t,w,n;
}a[MAX_M];
deque <int> q;
int ls[MAX_N],b[MAX_N],K[MAX_N],n,m,k,s,t;
bool v[MAX_N],f[11];
long long d[11][MAX_N],Min=maxlongint;

void spfa(int p,int s)
{
    for (int i=1;i<=n;i++)
        d[p][i]=maxlongint;
    d[p][s]=0; v[s]=1;
    q.push_back(s);
    while (!q.empty())
    {
        int u=q.front(); q.pop_front();
        v[u]=0;
        for (int i=ls[u];i;i=a[i].n)
            if (d[p][u]+a[i].w<d[p][a[i].t])
            {
                d[p][a[i].t]=d[p][u]+a[i].w;
                if (!v[a[i].t])
                {
                    v[a[i].t]=1;
                    if (q.empty() || d[p][a[i].t]>d[p][q.front()])
                        q.push_back(a[i].t);
                    else
                        q.push_front(a[i].t);
                }
            }
    }
}

void dfs(int dep,int p,long long s)
{
    if (dep>k)
    {
        s+=d[p][t];
        if (s<Min)
            Min=s;
        return;
    }
    for (int i=1;i<=k;i++)
        if (!f[i])
        {
            f[i]=1;
            dfs(dep+1,i,s+d[p][K[i]]);
            f[i]=0;
        }
}

int main()
{
    scanf("%d%d%d%d%d",&n,&m,&k,&s,&t);
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&a[i].f,&a[i].t,&a[i].w);
        a[i].n=ls[a[i].f];
        ls[a[i].f]=i;
    }
    spfa(0,s);
    for (int i=1;i<=k;i++)
    {
        scanf("%d",&K[i]);
        spfa(i,K[i]);
    }
    dfs(1,0,0);
    if (Min!=maxlongint)
        printf("%lld",Min);
    else
        printf("-1");
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章