题意
给你一个n点m边的图,让你从1走到n,找到一条经过尽量多点的路径,且路径边权和小于等于T
然后输出路径。
分析:自己原本打算5000*5000×vector 果断爆了。。
然后用最短路的方式,dp【Node】里面记录cost和num,又在case35TLE。
- 看了别人,还是要好好学学记录路径的方法。。。
- 2.
别人的代码。。400ms
最短路spfa(一敲)220600 KB (所以其实是卡着空间过的。。把一个东西改为bool。。。
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define MP(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=a;i<=b;++i)
#define FOR(i,a,b) for(int i=a;i<b;++i)
#define pii pair<int,int>
#define sf scanf
#define pf printf
const int maxn = 5000;
int n, m, lim;
int h[maxn+5], e[maxn+5], cost[maxn+5], nex[maxn+5];
int dis[maxn+3][maxn+3];
char inq[maxn+3][maxn+3];
int pre[maxn+3][maxn+3];
int sta[maxn+3];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int u, v, w;
sf("%d%d%d", &n, &m, &lim);
REP(i,1,m)
{
sf("%d%d%d", &u, &v, &w);
e[i] = v, cost[i] = w, nex[i] = h[u], h[u] = i;
}
pii tmp, tmp2;
int dist;
queue<pii> que;
mem(dis, 0x7f);
dis[1][1] = 0, inq[1][1] = 1, pre[1][1] = 0;
que.push( MP(1,1) );
while(!que.empty())
{
tmp = que.front(); que.pop();
inq[tmp.first][tmp.second] = 0;
int &x = tmp.first;
for(int i=h[x]; i; i=nex[i]) {
tmp2.first = e[i];
tmp2.second = tmp.second+1;
dist = dis[x][tmp.second] + cost[i];
if(dist > lim) continue;
if(dist < dis[tmp2.first][tmp2.second]) {
dis[tmp2.first][tmp2.second] = dist;
pre[tmp2.first][tmp2.second] = x;
if(!inq[tmp2.first][tmp2.second]) {
inq[tmp2.first][tmp2.second] = 1;
que.push(tmp2);
}
}
}
}
int ans, now;
for(int i=n; i>=2; --i)
if(dis[n][i] <= lim)
{
pf("%d\n", ans=i);
break;
}
now = n;
while(now)
{
sta[++sta[0]] = now;
now = pre[now][ans--];
}
for(int i=sta[0]; i>=1; --i)
{
if(i<sta[0]) pf(" ");
pf("%d", sta[i]);
}
pf("\n");
return 0;
}
还有。。62ms
记录后继+ dp
#include <bits/stdc++.h>
#define pr(x) cout << #x << "= " << x << " " ;
#define pl(x) cout << #x << "= " << x << endl;
#define ll __int64
#define mst(ss,b) memset(ss,b,sizeof(ss));
using namespace std;
const int N=5050;
const int inf=0x3f3f3f3f;
int n, m, T;
int f[N][N];//f[i][j]表示当前在点i,接下来经过j个点(包括自己)到n点的最小距离
short nxt[N][N];//nxt[i][j]表示当前在点i,接下来经过j个点(包括自己)到n点的后继
vector< pair<int,int> >a[N];
bool vis[N];
void dfs(int x){
if (vis[x])return; vis[x] = 1;
for (auto it : a[x]){
dfs(it.first);
for (int i = 2; i <= n; ++i){
int dis = f[it.first][i - 1] + it.second;
if (dis < f[x][i]){
f[x][i] = dis;
nxt[x][i] = it.first;
}
}
}
}
void print(){
for (int i = n; ; --i)if (f[1][i] <= T){
printf("%d\n", i);
int x = 1; printf("%d ", x);
while (x != n){
x = nxt[x][i--];
printf("%d ", x);
}puts("");
break;
}
}
int main(){
while(~scanf("%d%d%d",&n, &m, &T)){
for (int i = 1; i <= n; ++i)a[i].clear(), vis[i] = 0;
for (int i = 1; i <= m; ++i){
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
if (y == 1 || x == n)continue;
a[x].push_back({ y,z });
}
mst(f, inf);
f[n][1] = 0; vis[n] = 1;
dfs(1);
print();
}
return 0;
}