单源最短路的简单建图
思路:只要两个点之间可达,距离就是1
每个车站到达后面的车站的距离都是1
那么1到达n的最短距离就是转车次数+1由于距离都是1,可以用bfs求最短路
注意:
这里的车站是单程的
技巧:
sstream读入
#include <cstring>
#include <iostream>
#include <algorithm>
#include <sstream>
using namespace std;
const int N = 510;
int m, n;
bool g[N][N];
int dist[N];
int stop[N];
int q[N];
void bfs()
{
int hh = 0, tt = 0;
memset(dist, 0x3f, sizeof dist);
q[0] = 1;
dist[1] = 0;
while (hh <= tt)
{
int t = q[hh ++ ];
for (int i = 1; i <= n; i ++ )
if (g[t][i] && dist[i] > dist[t] + 1)
{
dist[i] = dist[t] + 1;
q[ ++ tt] = i;
}
}
}
int main()
{
cin >> m >> n;
string line;
getline(cin, line);
while (m -- )
{
getline(cin, line);
stringstream ssin(line);
int cnt = 0, p;
while (ssin >> p) stop[cnt ++ ] = p;
for (int j = 0; j < cnt; j ++ )
for (int k = j + 1; k < cnt; k ++ )
g[stop[j]][stop[k]] = true;
}
bfs();
if (dist[n] == 0x3f3f3f3f) puts("NO");
else cout << dist[n] - 1 << endl;
return 0;
}
思路:超级源点
直观的想,我们最容易想到的思路是从我们的目标物开始往下寻找替代品,对于寻找到的替代品,看看有没有该替代品的替代品。即cost[root] = new_money + cost[tmp],然后再递归求cost[tmp],以此往复。
但是这样的话就是一个DFS了,由于本题n=100,所以dfs是不可行的。
既然我们不能从头开始寻找一条最短路,那么我们能不能从尾开始求一条最短路呢,这样就不用递归了。
事实上我们不能从尾开始找到一条最短路,或者说我们不能直接从尾找到一条最短路,因为我们的尾有很多,但在求最短路的时候,只能有一个尾巴。
——————————————————正解———————————————————
所以说,我们建立一个超级源点0,从0建立一条边到每个物品,权值为物品的价值。代表花费多少钱就可以购买这个物品。
若某个物品拥有替代品,代表从替代品建立一条边到这个物品,价值为替代的价值。 代表我有了这个替代品,那么还需要花费多少就能买这个物品。
最后就是等级制度。我们可以枚举每个等级区间,每次求最短路是只能更新在这个区间里面的物品。枚举所有情况求一个最小值就可以了。 特别注意的是区间必须包含1点。 那么范围就是【L[1] - m, L[1]】
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110;
int g[N][N], level[N];
int n, m;
int dist[N];
bool st[N];
int dijkstra(int l, int r)
{
memset(dist, 0x3f, sizeof dist);
memset(st, false, sizeof st);
dist[0] = 0;//从虚拟源点出发
for(int u = 1; u <= n; u ++ )
{
int t = -1;
for(int i = 0; i <= n; i ++ )
if(!st[i] && (t == -1 || dist[i] < dist[t]))
t = i;
st[t] = true;
//如果选取的点不符合区间范围
if(t && level[t] < l || level[t] > r) //当选取的点是虚拟源点时需要特判
continue;
for(int i = 1; i <= n; i ++ )
if(level[i] >= l && level[i] <= r)//被更新的点也要满足区间范围
dist[i] = min(dist[i], dist[t] + g[t][i]);
}
return dist[1];
}
int main()
{
memset(g, 0x3f, sizeof g);
for(int i = 0; i <= n; i ++ ) g[i][i] = 0;
cin >> m >> n;
for(int i = 1; i <= n; i ++ )
{
int price, k, id, cost;
cin >> price >> level[i] >> k;
g[0][i] = min(g[0][i], price);
while(k -- )
{
cin >> id >> cost;
g[id][i] = min(g[id][i], cost);
}
}
int res = 0x3f3f3f3f;
for (int i = level[1] - m; i <= level[1]; i ++ ) res = min(res, dijkstra(i, i + m));
cout << res << endl;
return 0;
}