题意:坐飞机从 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
*/