湫湫系列故事——过年回家

Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 1266    Accepted Submission(s): 282


Problem Description
  出门在外,最想念的还是家,对在深圳腾讯工作的HR湫湫来说,春节回家是一年中最期盼的事,不仅可以见到阔别已久的亲人,还能以相亲的名义调侃众多帅哥(她的内心告诉她:如果相亲能遇到参加过腾讯编程马拉松的同学,就直接把自己嫁了~)。
   同时,每年的春节湫秋也都会纠结一把,因为车票实在是太难抢了,不过2013的春节有点特殊,作为一个曾经的ACMer,湫湫制作出了很完美的刷票机, 也就是说她再也不用担心买不上票了,但是想来想去还是觉得随便买票实在是浪费了辛辛苦苦搞出来的刷票机,所以她决定要用最舒适的方式回家。
  假 设湫湫有可能经过的n个城市分别编号从1到n,湫湫要从城市A回到城市B,购票网站上列出了t辆列车行程,每辆车的行程用一个字符串表示,途径的城市间 用+号相连,如1+2+3+5代表一辆从1城市分别经过2,3到达5的火车,湫湫可以从中间任意一站出发和下车(路径是单向的,即必须沿字符串从左到右来 走),每个字符串对应着一个整数k,k=0表示该车只有硬座,k=1表示该车有卧铺也有硬座,在整个回家的计划中,同一辆车可以坐无限次,为了中途换车的 方便,如果在起点坐的是卧铺,则后面乘坐的车必须全是卧铺,同样的,如果在起点坐的是硬座,则后面乘坐的车必须全是硬座,假设一段(一辆车行程中,两相邻 城市间为一段)硬座的不舒适度是D1,一段卧铺的不舒适度是D2,求湫湫回家最小的不舒适度。
 

 

Input
  输入数据的第一行包含一个整数Q,表示测试数据的组数;
  每组数据的第一行是2个正整数n和t,分别表示城市数和列车数;
  接下来t行,每行一个字符串表示列车行程,字符串长度小于10000,每个字符串后跟一个整数k(k为0或1),之间用空格隔开;
  接下来一行是D1,D2,其含义见题目描述;
  最后一行是2个正整数A和B,表示起始和终点城市。

  [Technical Specification]
  1 <= Q <= 100
  1 < n <= 200
  1 < t <= 1000
  0 < D1 <= 10000, 0 < D2 <= 10000,D1和D2的大小关系不确定
  1 <= A, B <= n 且 A <> B
 

 

Output
  对于每组数据,如果湫湫可以到达目的地,则输出一个整数,表示湫湫到家所需的最小不舒适度。如果不能到达则直接输出-1。
 

 

Sample Input
1 6 5 2+4+3+5+1+6 1 5+4+2+3+1 1 3+2+5+1+6 1 6+2 0 6+3+1+4+5+2 0 3 2 5 3
 

 

Sample Output
4
 

 

Source
 
这个题有两种情况,一种是只坐硬座,一种是只坐卧铺,构两张图出来进行最短路即可。
构图被坑惨了。。。天真的以为是隔着'+'号跳两边就是城市....
///构造两个图,一个是卧铺,一个是硬座
#include<stdio.h>
#include<string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF =999999999;
const int N = 300;
int graph[N][N],graph1[N][N]; ///graph 是卧铺,graph1是硬座
char str[10005];
int n,t,d1,d2;
void init()
{
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            if(i==j) graph[i][j] = 0,graph1[i][j]=0;
            else graph[i][j] = INF,graph1[i][j]=INF;
        }
    }
}
bool vis[N];
int low[N];
int dijkstra(int s,int e,int g[][N])
{
    for(int i=1; i<=n; i++)
    {
        vis[i] = false;
        low[i] = g[s][i];
    }
    vis[s] = true;
    for(int i=1; i<n; i++)
    {
        int MIN = INF;
        for(int j=1; j<=n; j++)
        {
            if(!vis[j]&&MIN>low[j])
            {
                MIN = low[j];
                s = j;
            }
        }
        vis[s] = true;
        for(int j=1; j<=n; j++)
        {
            if(!vis[j]&&low[j]>g[s][j]+low[s])
            {
                low[j] = g[s][j]+low[s];
            }
        }
    }
    return low[e];
}
int main()
{
    int tcase;
    scanf("%d",&tcase);
    while(tcase--)
    {
        scanf("%d%d",&n,&t);
        init();
        int v;
        /*for(int i=1;i<=t;i++){
            scanf("%s %d",str,&v);
            int len = strlen(str);
            int pre = str[0]-'0',now;
            for(int j=2;j<len;j+=2){ ///错误代码!!!!!!我这样写比如说:'12'是取不到的!!!!
                now = str[j]-'0';
                if(v==1){
                    graph[pre][now] = 1;
                    graph1[pre][now] = 1;
                }
                else graph1[pre][now] = 1; ///为0时只构造graph1,graph不存在硬座
                pre = now;
            }
        }*/
        for(int i=1; i<=t; i++)
        {
            scanf("%s %d",str,&v);
            int len = strlen(str);
            int K;
            int pre = 0;
            int k = 0;
            while(str[k]!='+')
            {
                pre = pre*10+str[k]-'0';
                k++;
            }
            for(int j=k+1; j<len; j++)
            {
                int now = 0;
                while(j<len&&str[j]!='+')
                {
                    now = now*10+str[j]-'0';
                    j++;
                }
                if(v==1)
                {
                    graph[pre][now] = 1;
                    graph1[pre][now] = 1;
                }
                else graph1[pre][now] = 1; ///为0时只构造graph1,graph不存在硬座
                pre = now;
            }
        }
        scanf("%d%d",&d1,&d2);
        int s,e;
        scanf("%d%d",&s,&e);
        int m1 = dijkstra(s,e,graph); ///卧铺的最小舒适度
        int m2 = dijkstra(s,e,graph1);
        if(m1>=INF&&m2>=INF) printf("-1\n");
        else if(m1>=INF)
        {
            printf("%d\n",m2*d1);
        }
        else if(m2>=INF)
        {
            printf("%d\n",m1*d2);
        }
        else printf("%d\n",min(m1*d2,m2*d1));
    }
    return 0;
}

/*
6 4
3+4 1
4+2+6 0
3+2+1+6 1
3+1+5+2+6 0
3 2
5 6
*/