721C:Journey
题意简述
给出一个
n
个点
问从
1
到
数据范围
1≤k,wi≤109
思路
拓扑排序一下。
f[i][j]
表示到
i
号点,经过
状态转移方程:
f[i][j]=min(f[i][j],f[pre[i]][j−1]+e.w)
这B卡内存…
把保存方案的数组用short存一下..
代码
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define INF 1LL<<60
struct edge{
int s,t,cap,next;
}e[5010];
int head[5010],cnt;
void addedge(int s,int t,int cap)
{
e[cnt].s=s;e[cnt].t=t;e[cnt].cap=cap;e[cnt].next=head[s];head[s]=cnt++;
}
int n,m,k,u,v,w;
int degree[5010],ans[5010];
long long f[5010][5010];
short pre[5010][5010];
queue<int> q;
int main()
{
scanf("%d%d%d",&n,&m,&k);
memset(head,0xff,sizeof(head));
cnt=0;
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
degree[v]++;
}
for (int i=1;i<=n;i++)
if (!degree[i])
q.push(i);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
f[i][j]=INF;
f[1][1]=0;
while (!q.empty())
{
int tmp=q.front();
q.pop();
for (int i=head[tmp];i!=-1;i=e[i].next)
{
degree[e[i].t]--;
for (int j=2;j<=n;j++)
if (f[tmp][j-1]+e[i].cap<f[e[i].t][j])
{
f[e[i].t][j]=f[tmp][j-1]+e[i].cap;
pre[e[i].t][j]=tmp;
}
if (!degree[e[i].t])
q.push(e[i].t);
}
}
for (int i=n;i>=2;i--)
if (f[n][i]<=k)
{
printf("%d\n",i);
int tmp=n;
for (int j=i;j>=1;j--)
{
ans[j]=tmp;
tmp=pre[tmp][j];
}
for (int j=1;j<=i;j++)
printf("%d%c",ans[j]," \n"[j==i]);
break;
}
return 0;
}