Uva10806

这题是要你求从顶点1到顶点n然后再从n到1的最小的花费,注意两次走的边不能有相同的。。。原本单蠢的以为求一遍最短路,然后把边给删掉。。然后在跑一遍。后来想想不行啊,这样第一次的最短路会造成第二次回去无路可走。

其实关键是在求第二次的最短路的时候我们要对图进行一下处理,把无向图转变为有向图。我们先把一个次走过的边的权值变成0,然后再把它的反向变的权值转为相反数。这样两次一定要走的路的权值就会抵消掉,相当于没走= =

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
const int N=110;
#define inf 9999999
#include<queue>
using namespace std;
int d[N],p[N];//p数组记录的是前驱顶点
int g[N][N];
int n;
int spfa()
{
    for(int i=0;i<=n;i++)
    d[i]=inf;
    d[1]=0;
    queue<int>q;
    q.push(1);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int v=1;v<=n;v++)
        {
            if(g[u][v]&&d[v]>d[u]+g[u][v])
            {
                d[v]=d[u]+g[u][v];
                p[v]=u;
                q.push(v);
            }
        }
    }
    if(d[n]==inf)
    return 1;
    else
    return 0;
}
int main()
{
    int m;
    while(scanf("%d",&n)!=EOF&&n)
    {
        memset(g,0,sizeof(g));
        scanf("%d",&m);
        int a,b,c;
        while(m--)
        {
            scanf("%d %d %d",&a,&b,&c);
            g[a][b]=g[b][a]=c;
        }
        int ans=0;
        if(spfa())
        {
            printf("Back to jail
");
        }
        else
        {
            ans+=d[n];
            for(int i=n;i!=1;i=p[i])
            {
                g[p[i]][i]=0;
                g[i][p[i]]=-g[i][p[i]];
            }
            if(spfa())
            printf("Back to jail
");
            else
            printf("%d
",ans+d[n]);
        }
    }
    return 0;
}
 
原文地址:https://www.cnblogs.com/NaCl/p/4902537.html