题意:给你一个有向图,让你求从1走到n最多能经过多少点,权值和小于t.
n<=5000。
分析:这其实就是一个DAG上求最短路最长,dp就可以了,暴力一点,设f[i,j]表示从1-i走过j个点的最小时间。注意有可能是环所以dfs到n的时候直接退出。方案的话随便记录一下就行了。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
int n,m;
const int N=1e6;
const int inf=1e9;
int t,tot=0,vis[N],next[N],go[N],head[N],val[N],f[5005][5005],pre[N],c[N];
inline void add(int x,int y,int z)
{
go[++tot]=y;
val[tot]=z;
next[tot]=head[x];
head[x]=tot;
}
inline void dfs(int x)
{
if (x==n)return;
int i=head[x];
vis[x]=1;
while (i)
{
int v=go[i];
if(!vis[v])
{
fo(j,1,n)
if (f[x][j-1]<inf)
if (f[v][j]>f[x][j-1]+val[i])
{
f[v][j]=f[x][j-1]+val[i];
pre[v]=x;
}
dfs(v);
}
i=next[i];
}
}
inline void print(int x,int y)
{
if (x==0)return;
c[++tot]=y;
y=pre[y];
print(x-1,y);
}
int main()
{
scanf("%d%d%d",&n,&m,&t);
fo(i,1,m)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
memset(f,127,sizeof(f));
f[1][1]=0;
//f[1][0]=0;
dfs(1);
int ans=0;
tot=0;
fd(i,n,1)if (f[n][i]<=t)
{
ans=i;
printf("%d\n",ans);
print(ans,n);
fd(j,tot,1)printf("%d ",c[j]);
printf("\n");
break;
}
return 0;
}