Codeforces 721C [dp][拓扑排序]

/*
题意:给你一个有向无环图。给一个限定t。
问从1点到n点,在不超过t的情况下,最多可以拜访几个点。
保证至少有一条路时限不超过t.
思路:
1.由无后向性我们可以知道(取决于该图是一个DAG),这题一定可以dp。
2.dp[i][j]代表,到达点i,并且拜访了j个城市的最短时间。
wa点:
没有初始化数组中的0..
*/

#include<bits/stdc++.h>
#define N 5050
using namespace std;
int inf=0x3f3f3f3f;
int num[N];
bool vis[N];
int dp[N][N];
struct edge{
    int id;
    int w;
    edge *next;
};
edge edges[N];
edge *adj[N];
int ednum;
inline void addedge(int a,int b,int w){
    edge *tmp=&edges[ednum++];
    tmp->id=b;
    tmp->w=w;
    tmp->next=adj[a];
    adj[a]=tmp;
}
int fromx[N][N];
int main()
{
    int n,m,t,a,b,w;
    scanf("%d%d%d",&n,&m,&t);
    for(int i=0;i<=n;i++){
        for(int j=1;j<=n;j++){
            dp[i][j]=inf;
        }
    }
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&a,&b,&w);
        addedge(a,b,w);
        num[b]++;
    }
    dp[1][1]=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(vis[j]||num[j])continue;
            vis[j]=1;
            for(edge *it=adj[j];it;it=it->next){
                num[it->id]--;
                for(int k=2;k<=n;k++){
                    if(dp[it->id][k]>dp[j][k-1]+it->w){
                        dp[it->id][k]=dp[j][k-1]+it->w;
                        fromx[it->id][k]=j;
                    }
                }
            }
            break;
        }
    }

    for(int i=n;i>=2;i--){
        if(dp[n][i]<=t){
            printf("%d
",i);
            stack<int>ss;
            int x=n,y=i;
            ss.push(n);
            while(fromx[x][y]!=1){
                ss.push(fromx[x][y]);
                x=fromx[x][y];
                y--;
            }
            ss.push(1);
            while(!ss.empty()){
                int pp=ss.top();
                ss.pop();
                printf("%d ",pp);
            }
            break;
        }
    }

}
原文地址:https://www.cnblogs.com/tun117/p/5925471.html