1. 程式人生 > >sdut 2622 最短路徑(Dijkstra演算法求最短路)

sdut 2622 最短路徑(Dijkstra演算法求最短路)

最短路徑

Time Limit: 1000ms   Memory limit: 65536K  有疑問?點這裡^_^

題目描述

為了準備一年一度的校賽,大家都在忙著往賽場搬運東西,比如氣球什麼的。這時 YY 也沒有閒著,他也加入了搬運工的行列。已知學校有 N 個路口和 M 條路,YY 並不是把東西直接搬到賽場,而是從 S 路口搬運到 T 路口。由於 YY 非常懶而且他有輕度強迫症。所以他要走的路需要儘可能的短,並且走過路徑的數目要為 X 的倍數。

輸入

輸入的第一行為一個正整數T(1 ≤ T ≤ 20),代表測試資料組數。

對於每組測試資料:

輸入的第一行為兩個正整數 N 和 M(1 ≤ N ≤ 100, 1 ≤ M ≤ 10000)。

接下來M行每行三個正整數 U、V、W(0 ≤ U, V < N, 0 ≤ W ≤ 230 ),代表有一條從U到V的長度為W的有向路徑。

最後一行為三個正整數S、T 、X(0 ≤ S, T < N, 1 ≤ X ≤ 10)。

輸出

對於每組測試資料,輸出滿足條件的從 S 到 T 的最短路徑。如果從 S 到 T 不可達,或者無法滿足路徑數是 X 的倍數,輸出“No Answer!”(不包含引號)。

注意:64-bit 整型請使用 long long 來定義,並且使用 %lld 或 cin、cout 來輸入輸出,請不要使用 __int64 和 %I64d。

示例輸入

2
2 1
0 1 1
0 1 2
3 2
0 1 1
1 2 1
0 2 2

示例輸出

No Answer!
2

提示

這題一定要寫部落格,搞了我好久,無論是二維SPFA,還是三維Floyd,要麼TLE,要麼WA,最後終於借鑑了→http://www.cnblogs.com/luyingfeng/p/3621844.html
才AC(Dijkstra演算法).為了AC率用小號都交的都不好意思再交了。 題目要求到終點時走過的路徑數為x的倍數,那麼走到每個點就有x個種類,建立二維陣列,第二維記錄每種情況的狀態。

來源

 “師創杯”山東理工大學第五屆ACM程式設計競賽

示例程式

#include <stdio.h>
#define MAX 223372036854775807
long long map[100][100],d[100][10];	//map存圖,d存每個點不同情況的狀態
int vi[100][10];	//每個點的各種狀態是否遍歷過
void dij(int u,int v,int x,int n)
{
    int i,i1,pos,pos1,x1;
    long long t;
    for(i=0;n>i;i++)
    {
        for(i1=0;x>i1;i1++)
        {
            d[i][i1]=MAX;
            vi[i][i1]=0;
        }
    }
    d[u][0]=0;
    while(vi[v][0]==0)
    {
        t=MAX;
        pos=-1;
        for(i=0;n>i;i++)
        {
            for(i1=0;x>i1;i1++)
            {
                if(vi[i][i1]==0&&t>d[i][i1])
                {
                    t=d[i][i1];
                    pos=i;
                    pos1=i1;
                    x1=(i1+1)%x;	//步數記錄
                }
            }
        }
        if(pos==-1)
        {
            break;	//起點到終點沒有連通
        }
        vi[pos][pos1]=1;
        for(i=0;n>i;i++)
        {
            if(vi[i][x1]==0&&d[i][x1]>t+map[pos][i])
            {
                d[i][x1]=t+map[pos][i];
            }
        }
    }
}
int main()
{
    int i,t,n,m,i1,i2,u,v,w,x;
    scanf("%d",&t);
    for(i=1;t>=i;i++)
    {
        scanf("%d %d",&n,&m);
        for(i1=0;n>i1;i1++)
        {
            for(i2=0;n>i2;i2++)
            {
                map[i1][i2]=MAX;
            }
        }
        for(i1=1;m>=i1;i1++)
        {
            scanf("%d %d %d",&u,&v,&w);
            if(map[u][v]>w)		//防止重邊
            {
                map[u][v]=w;
            }
        }
        scanf("%d %d %d",&u,&v,&x);
        dij(u,v,x,n);		//Dijkstra演算法
        if(d[v][0]!=MAX)
        {
            printf("%lld\n",d[v][0]);
        }
        else
        {
            printf("No Answer!\n");
        }
    }
    return 0;
}
 



/**************************************
	Problem id	: SDUT OJ 2622 
	Code Len	: 1720B 
	Result		: Accepted 
	Take Memory	: 388K 
	Take Time	: 20MS 
	Submit Time	: 2016-07-19 09:53:50  
**************************************/