[CF721C]Journey

来源:互联网 发布:质量问题淘宝怎么陪 编辑:程序博客网 时间:2024/06/05 19:56

721C:Journey

题意简述

给出一个n个点m条边的有向无环图。
问从1n,在距离不超过k的情况下最多经过多少点,并输出一个方案。

数据范围

1n,m5000
1k,wi109

思路

拓扑排序一下。
f[i][j]表示到i号点,经过j个点的最小花费。
状态转移方程:
f[i][j]=min(f[i][j],f[pre[i]][j1]+e.w)
这B卡内存…
把保存方案的数组用short存一下..

代码

#include<cstdio>#include<cstring>#include<queue>using namespace std;#define INF 1LL<<60struct 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;}
0 0