题目看上去感觉像是dijstra,但是不是最短路,而是在实践允许的范围内选择最多的点去走完从1到n的路,这个想到的是动态规划,以边为核心,一条边一条边的扫过,如果这条边对应的起点和终点连接上之后,对于从1到终点来说是有利的就加上那种,我还不是很理解,只是把标程看懂自己敲了一遍而已。
#include<iostream>
using namespace std;
#include<stack>
const int inf = 0x3f3f3f;//特别大的数,记下来
const int maxn = 5005;
int dp[maxn][maxn], pre[maxn][maxn];
//dp[i][j]表示经过i个点,从1到j,其中点的个数包括j
struct edge
{
int u, v, w;
}eg[maxn];
int n, m, t;
stack<int>reu;
int main()
{
while (cin >> n >> m >> t)
{
memset(dp, inf, sizeof(dp));
memset(pre, -1, sizeof(pre));
int i;
for (i = 0; i < m; i++)
cin >> eg[i].u >> eg[i].v >> eg[i].w;
int j;
int pos;
dp[1][1] = 0;//从1到1必然是0
for (i = 2; i <= n; i++)//从2开始循环,到n个点
{
for (j = 0; j < m; j++)//扫过每条边
{
int u = eg[j].u;
int v = eg[j].v;
int w = eg[j].w;
if (dp[i - 1][u] + w < dp[i][v])//关键的动态规划的过程
{
dp[i][v] = dp[i - 1][u] + w;
pre[i][v] = u;//表示经过i个点到达v之后,前一个点是u
}
}
if (dp[i][n] <= t)
pos = i;//更新一次答案
}
cout << pos << endl;
int ans = n;
while (ans != -1)
{
reu.push(ans);
ans = pre[pos--][ans];//所以pre是一个用来记录路线的数组
}
while (!reu.empty())
{
cout << reu.top() << " ";
reu.pop();
}
cout << endl;
}
return 0;
}
希望日后可以对dp有更深的理解!