HDU 4522

假设湫湫有可能经过的n个城市分别编号从1到n,湫湫要从城市A回到城市B,购票网站上列出了t辆列车行程,每辆车的行程用一个字符串表示,途径的城市间用+号相连,如1+2+3+5代表一辆从1城市分别经过2,3到达5的火车,湫湫可以从中间任意一站出发和下车(路径是单向的,即必须沿字符串从左到右来走),每个字符串对应着一个整数k,k=0表示该车只有硬座,k=1表示该车有卧铺也有硬座,在整个回家的计划中,同一辆车可以坐无限次,为了中途换车的方便,如果在起点坐的是卧铺,则后面乘坐的车必须全是卧铺,同样的,如果在起点坐的是硬座,则后面乘坐的车必须全是硬座,假设一段(一辆车行程中,两相邻城市间为一段)硬座的不舒适度是D1,一段卧铺的不舒适度是D2,求湫湫回家最小的不舒适度。

因为题目要求只能一直都坐硬卧或一直都坐软卧,所以要2遍最短路。

View Code
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

const int Max = 209;
#define inf 1<<28
#define min(a,b) a<b?a:b
int mat[Max][Max];
int map[Max][Max];
char ss[Max*100];
int dis[Max];
bool vis[Max];
int n,m;

void dij1(int s) {
    memset(vis,0,sizeof(vis));
    for(int i = 1; i <=n ; i++)
        dis[i] = mat[s][i];
    vis[s] = 1;
    while(1) {
        int mmin = inf;
        int p = -1;
        for(int i = 1; i <= n; i++) {
            if(dis[i] < mmin && !vis[i]) {
                p = i;
                mmin = dis[i];
            }
        }
        if(p == -1)
            break;
        vis[p] = 1;
        for(int i = 1; i <= n; i++) {
            if(!vis[i] && dis[i] > dis[p] + mat[p][i])
                dis[i] = dis[p] + mat[p][i];
        }
    }
}

void dij2(int s) {
    memset(vis,0,sizeof(vis));
    for(int i = 1; i <=n ; i++)
        dis[i] = map[s][i];
    vis[s] = 1;
    while(1) {
        int mmin = inf;
        int p = -1;
        for(int i = 1; i <= n; i++) {
            if(dis[i] < mmin && !vis[i]) {
                p = i;
                mmin = dis[i];
            }
        }
        if(p == -1)
            break;
        vis[p] = 1;
        for(int i = 1; i <= n; i++) {
            if(!vis[i] && dis[i] > dis[p] + map[p][i])
                dis[i] = dis[p] + map[p][i];
        }
    }
}

int main() {
    int t;
    scanf("%d",&t);
    while(t--) {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=n;j++) {
                mat[i][j] = inf;
                map[i][j] = inf;
            }
        }
        for(int i=0;i<m;i++) {
            int x;
            scanf("%s",ss);
            scanf("%d",&x);
            int len = strlen(ss);
            int s1 = 0,s2 = 0;
            int j = 0;
            while(ss[j] != '+') {
                s1 = s1*10 + ss[j]-'0';
                j++;
            }
            for(j++; j < len ;j++) {
                while(ss[j] != '+' && j < len) {
                    s2 = s2*10 + ss[j]-'0';
                    j++;
                }
                if(x == 1)
                    mat[s1][s2] = 1;
                else
                    mat[s1][s2] = 0;
                s1 = s2;
                s2 = 0;
            }
        }
        int v1,v2;
        int s,e;
        scanf("%d%d",&v1,&v2);
        scanf("%d%d",&s,&e);
        for(int i = 1;i <= n;i++) {
            for(int j = 1; j <= n; j++) {
                if(mat[i][j] == 1){
                    map[i][j] = v2;
                    mat[i][j] = v1;
                }
                else if(mat[i][j] == 0)
                    mat[i][j] = v1;
            }
        }
        dij1(s);
        int ans1 = dis[e];
        dij2(s);
        int ans2 = dis[e];
        int ans = min(ans1,ans2);
        if(ans >= inf)
            printf("-1\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/gray035/p/2982923.html