hdu 1385 最短路+字典序比较 Minimum Transport Cost

时间:2022-02-06 04:28:29

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1385

题目意思很明确,这里就不讲了

从这道题的年份来看,n应该不会超过100,没有用floyd( 效率不高,不喜欢用),选择了dijkstra

注意两个点:一.起点和终点一样的情况,容易解决

二.字典序大小比较时,要把当前的点加进路径比较,discuss有个例子

4
0 2 3 9
2 0 1 5
3 1 0 3
9 5 3 1
0 0 0 0
1 4
------------
output应该是 1->2->3->4这条路径吧。以前我的是 1->3->4也a了(原话,完全引用)
当前点不加进结果就会变成1->3->4,我看别人过了,以为我的也能过,WA几次了才决定改正,可能这组数据真的被加上去了
#include<iostream>
#include<queue>
#include<cstdlib>
#include<stack>;
#define MAXN 1010
#define INF 100000001
using namespace std;
int n,m;
typedef pair<int ,int >pii;
priority_queue<pii,vector<pii>,greater<pii>   >q;
stack<int>que;
int dis[MAXN],vis[MAXN],f[MAXN],cha[MAXN];
int map[MAXN][MAXN];
void init()
{
    int i;
    for(i=0;i<=n;i++)
    {
        dis[i]=INF;
        vis[i]=0;
        f[i]=i;
    }
}
int check(int x,int y,int k)
{
    int i;
    int a[110],b[110];
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    while(f[x]!=x)
    {
        que.push(x);
        x=f[x];
    }
    que.push(x);
    i=0;
    while(!que.empty())
    {
        a[i++]=que.top();
        que.pop();
    }
    a[i++]=k;//当前路径的最后一个元素
    //-----------------
    while(f[y]!=y)
    {
        que.push(y);
        y=f[y];
    }
    que.push(y);
    i=0;
    while(!que.empty())
    {
        b[i++]=que.top();
        que.pop();
    }
    b[i++]=k;//当前路径的最后一个元素
    for(i=0;i<100;i++)
    {
        if(a[i]>b[i])
            return 2;
        else if(a[i]<b[i])
            return 1;
    }
    return 0;
}
void dij(int x)
{
    int i;
    dis[x]=0;
    q.push(make_pair(0,x));
    while(!q.empty())
    {
        pii tt=q.top();
        q.pop();
        int v=tt.second;
        if(vis[v])
            continue;
        vis[v]=1;
        for(i=1;i<=n;i++)
        {
            if(vis[i]==0&&dis[i]>dis[v]+map[v][i]+cha[i])
            {
                dis[i]=dis[v]+map[v][i]+cha[i];
                f[i]=v;
                q.push(make_pair(dis[i],i));
            }
            else if(vis[i]==0&&dis[i]==dis[v]+map[v][i]+cha[i])//相等时进行比较
            {
                if(check(f[i],v,i)==2)//将i加进路径比较
                    f[i]=v;
            }
        }
    }
}
int main()
{
    int i,j,k,x,y,a[110],yy;
    while(cin>>n,n)
    {
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
            {
                cin>>map[i][j];
                if(map[i][j]==-1)
                    map[i][j]=INF;
            }
        for(i=1;i<=n;i++)
            cin>>cha[i];
        while(cin>>x>>y,x!=-1||y!=-1)
        {
            yy=y;
            init();
            dij(x);
            printf("From %d to %d :\n",x,y);
            memset(a,0,sizeof(a));
            while(f[y]!=y)
            {
                que.push(y);
                y=f[y];
            }
            que.push(y);
            i=0;
            while(!que.empty())
            {
                a[i++]=que.top();
                que.pop();
            }
            k=i;
            printf("Path: ");
            for(i=0;i<k;i++)
            {
                if(i==0)
                    printf("%d",a[i]);
                else
                    printf("-->%d",a[i]);
            }
            printf("\n");
            if(x==yy)//注意判断两个点相同的情况
                printf("Total cost : %d\n\n",0);
            else
                printf("Total cost : %d\n\n",dis[yy]-cha[yy]);
        }
    }
}