codeforces 721C DAG上dp

来源:互联网 发布:用友重装后数据恢复 编辑:程序博客网 时间:2024/05/18 03:31

题意:给你一个有向图,让你求从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;}
0 0
原创粉丝点击