UVA 11374 Airport Express(最短路+枚举)

题目:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2369

题目大意:现在你要去机场,知道起点和终点,两种路线,商业型和经济型,商业型你只能乘一站,其他做经济型。给你m条经济型的边和k条商业型的边,并且最优解唯一。让你求出最优解的路线,打印出来,然后给出做商业型路线的那个站,最后给出最短时间。

解题思路:由于最多只有一站是商业型的路线,那么我们可以枚举这段路。其他的就是经济型的了,知道了这段路的两个端点a、b之后,加上起点到a和b到终点的最短路就是所枚举的这种情况下的最优解,然后取最小值即可。经济型的最短路,就相当于单源最短路,对起点和终点都用 dij 预处理一下就行了。注意,没两组测试数据之间要有空行。

但是,其实我第一遍不是这么做的,我的做法是做一遍两维的最短路,先给每条边加一个属性kind,0表示是经济的,1表示商业的,然后跑SPFA或dij,Node等也变为两维,0表示还没走过商业型,1表示已经走过。但是就是不知道为什么一直WA,自己造了几组数据都是对的。望高人解答!(代码见第二个)

代码如下(枚举):

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;

const int INF = 0x0fffffff;

const int MAXN = 555;
const int MAXM = 2222<<1;

struct Edge
{
    int t,v,kind,next;
}edge[MAXM];

int head[MAXN],tot;

void init()
{
    tot = 0;
    memset(head,-1,sizeof(head));
}

void add_edge(int s,int t,int val,int kind)
{
    edge[tot].t = t;
    edge[tot].v = val;
    edge[tot].kind = kind;
    edge[tot].next = head[s];
    head[s] = tot++;
}

struct Node
{
    int id,val;
    bool operator < (const Node& tmp) const
    {
        return val > tmp.val;
    }
};

priority_queue<Node> q;
int done[MAXN];

void dij(int s,int n,int* d,int* path)
{
    for(int i = 1;i <= n;i++) d[i] = INF;
    while(!q.empty())
        q.pop();
    memset(done,0,sizeof(done));
    q.push((Node){s,0});
    path[s] = -1;
    d[s] = 0;
    while(!q.empty())
    {
        Node cur = q.top();
        q.pop();
        if(done[cur.id]) continue;
        for(int i = head[cur.id];i != -1;i = edge[i].next)
        {
            int next_id = edge[i].t;
            int tmp = edge[i].v+cur.val;
            if(tmp < d[next_id])
            {
                d[next_id] = tmp;
                path[next_id] = cur.id;
                q.push((Node){next_id,tmp});
            }
        }
    }
}

int station;

void print(int& first,int u,int* path)
{
    if(u == -1) return ;
    print(first,path[u],path);
    if(first)
    {
        printf("%d",u);
        first = 0;
    }
    else printf(" %d",u);
}

void print2(int& first,int u,int* path)
{
    if(u == -1) return ;
    if(first)
    {
        printf("%d",u);
        first = 0;
    }
    else printf(" %d",u);
    print2(first,path[u],path);
}

int d[MAXN],g[MAXN];
int path_d[MAXN],path_g[MAXN];

int main()
{
    int cas = 0;
    int n,s,e;
    while(~scanf("%d%d%d",&n,&s,&e))
    {
        //if(cas++) puts("");

        int m;
        scanf("%d",&m);
        init();
        while(m--)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            add_edge(a,b,c,0);
            add_edge(b,a,c,0);
        }
        dij(s,n,d,path_d);
        dij(e,n,g,path_g);
        station = 0;
        int min_val = d[e];
        int aa,bb;
        int k;
        scanf("%d",&k);
        while(k--)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            int tmp = d[a]+c+g[b];
            if(tmp < min_val)
            {
                min_val = tmp;
                station = a;
                aa = a;
                bb = b;
            }
            swap(a,b);
            tmp = d[a]+c+g[b];
            if(tmp < min_val)
            {
                min_val = tmp;
                station = a;
                aa = a;
                bb = b;
            }
        }
        int first = 1;
        if(station == 0)
        {
            print(first,e,path_d);
            puts("");
            puts("Ticket Not Used");
        }
        else
        {
            //printf("aa = %d,bb = %d\n",aa,bb);
            print(first,aa,path_d);
            print2(first,bb,path_g);
            puts("");
            printf("%d\n",station);
        }
        printf("%d\n",min_val);
    }
    return 0;
}

/*

4 1 4
4
1 2 2
1 3 3
2 4 4
3 4 5
1
2 4 3

*/


代码如下(增加状态,WA):

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;

const int INF = 0x0fffffff;

const int MAXN = 555;
const int MAXM = 2222<<1;

struct Edge
{
    int t,v,kind,next;
}edge[MAXM];

int head[MAXN],tot;

void init()
{
    tot = 0;
    memset(head,-1,sizeof(head));
}

void add_edge(int s,int t,int val,int kind)
{
    edge[tot].t = t;
    edge[tot].v = val;
    edge[tot].kind = kind;
    edge[tot].next = head[s];
    head[s] = tot++;
}

int inq[MAXN][2];
int d[MAXN][2];

struct Node
{
    int id,kind;
};

queue<Node> q;

struct Path
{
    int id,kind;
}path[MAXN][2];

int ok[2];

void dij(int s,int e,int n)
{
    for(int i = 1;i <= n;i++) d[i][0] = d[i][1] = INF;
    while(!q.empty())
        q.pop();
    memset(inq,0,sizeof(inq));
    ok[0] = ok[1] = 0;
    q.push((Node){s,0});
    inq[s][0] = 1;
    path[s][0].id = -1;
    d[s][0] = 0;
    while(!q.empty())
    {
        Node cur = q.front();
        q.pop();
        inq[cur.id][cur.kind] = 0;
        for(int i = head[cur.id];i != -1;i = edge[i].next)
        {
            int next_id = edge[i].t;
            if(cur.kind == 1 && edge[i].kind == 1) continue;
            int next_kind = cur.kind|edge[i].kind;
            int tmp = edge[i].v+d[cur.id][cur.kind];
            if(tmp < d[next_id][next_kind])
            {
                d[next_id][next_kind] = tmp;
                path[next_id][next_kind] = (Path){cur.id,cur.kind};
                inq[next_id][next_kind] = 1;
                q.push((Node){next_id,next_kind});
            }
        }
    }
}

int station;

void print(int& first,int u,int kind)
{
    if(u == -1) return ;
    if(kind == 1 && path[u][kind].kind == 0) station = path[u][kind].id;
    print(first,path[u][kind].id,path[u][kind].kind);
    if(first)
    {
        printf("%d",u);
        first = 0;
    }
    else printf(" %d",u);
}

void solve(int s,int e,int n)
{
    dij(s,e,n);
    int min_val;
    station = 0;
    int first = 1;
    if(d[e][0] < d[e][1])
    {
        min_val = d[e][0];
        print(first,e,0);
    }
    else
    {
        min_val = d[e][1];
        print(first,e,1);
    }
    puts("");
    if(station == 0)
        puts("Ticket Not Used");
    else printf("%d\n",station);
    printf("%d\n",min_val);
}

int main()
{
    int cas = 0;
    int n,s,e;
    while(~scanf("%d%d%d",&n,&s,&e))
    {
        if(cas++) puts("");

        int m;
        scanf("%d",&m);
        init();
        while(m--)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            add_edge(a,b,c,0);
            add_edge(b,a,c,0);
        }
        int k;
        scanf("%d",&k);
        while(k--)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            add_edge(a,b,c,1);
            add_edge(b,a,c,1);
        }
        solve(s,e,n);
    }
    return 0;
}

/*

4 1 4
4
1 2 2
1 3 3
2 4 4
3 4 5
1
2 4 

5 5 1
3
1 2 4
2 3 4
3 4 4
5
1 2 2
2 3 2
1 3 2
2 4 2
4 5 10

*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值