POJ 3268 Silver Cow Party (單源最短路Dijkstra+反向構圖)

題目鏈接

POJ3268

題目大意

給定一個有N(1 N 1000)個結點、M(1 M105 )條單向邊的有向正權圖,求每個結點出發到X號結點再回來到初始位置的花費的最小值。

分析

對於每個結點,要在它與X號結點之間走一個來回花費最小,必定它到X要走最短路,從X回到它也要走最短路。
返回的最短路好解決,即X號結點出發到其他結點的單源最短路,用Dijkstra算法跑一遍即可。現在關鍵要解決從其他結點到X號結點的最短路,這種情況下起點是多個,而終點是一個,與單源最短路徑的情況恰好相反,如果再每個點作爲起點用Dijkstra複雜度就較高了。處理方法是:反向建圖,再求X到其他結點的單源最短路。(道路反向,起點與終點互換,問題等效)
最後答案爲Max(dis[i],dis2[i]).

代碼

#include <iostream>
#include <cstdio>
#include <cstring>
#define Max(a,b) (a>b?a:b)
using namespace std;
const int INF=99999999;
const int MAXN=1010;
const int MAXM=100010;
int e[MAXN][MAXN],e2[MAXN][MAXN],dis[MAXN],dis2[MAXN],book[MAXN],book2[MAXN];
int n,m,x;
void Init()//鄰接矩陣初始化
{
    int i,j;
    for (i=1;i<=n;i++)
        for (j=1;j<=n;j++)
            e[i][j]=(i==j?0:INF);
    for (i=1;i<=n;i++)
        for (j=1;j<=n;j++)
            e2[i][j]=(i==j?0:INF);
}
void Dijkstra()
{
    int i,j,u,v,mind;
    for (i=1;i<=n;i++)
        dis[i]=e[x][i];
    memset(book,0,sizeof(book));
    book[x]=1;
    for (i=1;i<=n-1;i++)
    {
        mind=INF;
        for (j=1;j<=n;j++)
            if (dis[j]<mind&&!book[j])
            {
                mind=dis[j];
                u=j;
            }
        book[u]=1;
        for (v=1;v<=n;v++)
            if ((e[u][v]<INF)&&(dis[v]>dis[u]+e[u][v]))
                dis[v]=dis[u]+e[u][v];
    }
}
void Dijkstra2()//對反向圖的計算
{
    int i,j,u,v,mind;
    for (i=1;i<=n;i++)
        dis2[i]=e2[x][i];
    memset(book2,0,sizeof(book2));
    book2[x]=1;
    for (i=1;i<=n-1;i++)
    {
        mind=INF;
        for (j=1;j<=n;j++)
            if (dis2[j]<mind&&!book2[j])
            {
                mind=dis2[j];
                u=j;
            }
        book2[u]=1;
        for (v=1;v<=n;v++)
            if ((e2[u][v]<INF)&&(dis2[v]>dis2[u]+e2[u][v]))
                dis2[v]=dis2[u]+e2[u][v];
    }
}
int main()
{
    int a,b,c,i,ans;
    scanf("%d%d%d",&n,&m,&x);
    Init();
    while (m--)
    {
        scanf("%d%d%d",&a,&b,&c);
        e[a][b]=c;
        e2[b][a]=c;//反向建圖
    }
    Dijkstra();
    Dijkstra2();
    ans=-1;
    for (i=1;i<=n;i++)
        ans=Max(ans,dis[i]+dis2[i]);
    printf("%d\n",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章