首页 > 代码库 > uva 11280 状态压缩+最短路

uva 11280 状态压缩+最短路

题意:坐飞机从 a 地到 b 地 ,在最多停留s次时 , 最小花费是多少?

在题目给出的地点 , 是按从远到近给出的 , 并且给出的航班中 , 不会有从远地点到近地点的航班。

因此从这可以看出 , 题目给的图是一个DAG图 , 那么我们就能用toposort来找最短路。


注意: 会有重边


解法:


构造一个数组 d[i][j]  , 表示从开始点 s  到点 i , 在停留 j 次时的最小花费。

然后我们再求出这个图的toposort , 再求这个每一个点和其相邻点的距离。


代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <queue>
#include <map>

using namespace std;

#define maxn 110
#define INF 0xfffffff


int grap[maxn][maxn] ;
long long d[maxn][maxn];
int n , m;
int s1 , t1;
int s;
int index1[maxn];  //存储每个点的入度
int topo[maxn];

void init()
{
    memset(grap , -1 , sizeof(grap));
    memset(index1 , 0 , sizeof(index1));
    s1 = 0 , t1 = n-1;
    s = n-2;
}
//可能会有重边

void add_edge(int x , int y , int z)
{
    if(grap[x][y] == -1)
    {
        grap[x][y] = z;
        index1[y] += 1;
    }
    else if(grap[x][y] > z)
        grap[x][y] = z;
}

void toposort()
{
    int i , u;
    int l = 0 , r = 0;
    for(i = 0; i < n; i++)
        if(index1[i] == 0)  topo[r++] = i;
    while(l < r)
    {
        u = topo[l++];
        for(i = 0; i < n; i++)
            if(grap[u][i] != -1 && index1[i] > 0)
            {
                index1[i]--;
                if(index1[i] == 0)
                    topo[r++] = i;
            }
    }
}

void spfa()
{
    int i , j;
    int u , v;
    for(i = 0; i < n; i++)
        for(j = 0; j <= s; j++)
            d[i][j] = INF;
    for(i = 0; i < n; i++)
        if(grap[s1][i] != -1)
            d[i][0] = grap[s1][i];

    j = 1;
    while(j < n)
    {
        u = topo[j];
        for(v = 0; v < s; v++)
        {
            if(d[u][v] == INF)  continue;
            for(i = 0; i < n; i++)
                if(grap[u][i] != -1)
                {
                    if(d[i][v+1] > d[u][v]+grap[u][i])
                    {
                        d[i][v+1] = d[u][v]+grap[u][i];
                    }
                }
        }
        j++;
    }
}

int main()
{
    //用map来区分每个点
    //cout<<INF<<endl;
    int t , cas = 1;
    scanf("%d" , &t);
    while(t--)
    {
        scanf("%d" , &n);
        init();
        map<string , int>ma;
        char city[30] , city2[30];
        int i , x , y , z;
        for(i = 0; i < n; i++)
        {
            scanf("%s" , city);
            ma[city] = i;
        }
        map<string,int>::iterator it;
        scanf("%d" , &m);
        for(i = 0; i < m ; i++)
        {
            scanf("%s %s %d" , city , city2 , &z);
            it=ma.find(city);
            x = it->second;
            it=ma.find(city2);
            y = it->second;
            add_edge(x , y , z);
        }
        int q;
        toposort();
        spfa();
        for(i = 1; i <= s; i++)
            d[t1][i]  = min(d[t1][i] , d[t1][i-1]);

        scanf("%d" , &q);
        printf("Scenario #%d\n" , cas++);
        for(i = 0; i < q; i++)
        {
            scanf("%d" , &x);
            x = x>s?s:x;
            if(d[t1][x] == INF)  cout<<"No satisfactory flights"<<endl;
            else  cout<<"Total cost of flight(s) is $"<<d[t1][x]<<endl;
        }
        if(t) cout<<endl;
    }

    return 0;
}
/*
2
4
Calgary
Winnipeg
Ottawa
Fredericton
7
Calgary Ottawa 350
Calgary Winnipeg 125
Calgary Ottawa 300
Winnipeg Fredericton 325
Winnipeg Ottawa 100
Calgary Fredericton 875
Ottawa Fredericton 175
3 2 1 0
3
Calgary
Montreal
Fredericton
2
Calgary Montreal 300
Montreal Fredericton 325
1 0
*/