CF 721C

题目:

找到一条加权和少于T的路线,使其经过的点数尽可能多,输出点的数量,并打印路线。

题解:

脑抽卡题了。。。这是题图上dp。

注意要点:

为了满足dp条件,必须拓扑排序。

在dp过程中利用prev记录路径。

dp[i][j],为了到达i需要经过j个结点的最小花费。

prev[i][j],最小花费的路线的前任结点。

用longlong可能会炸空间。

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<stack>
using namespace std;

const int INF=1e9+1;

struct Point{
    int cost,to;
    Point(){}
    Point(int to,int cost){
        this->cost=cost;
        this->to=to;
    }
};

int n,m,T;
queue<int> que;
vector<Point> vec[5010];
bool vis[5010];
int in_degree[5010];
int dp[5010][5010]; //经过j个点到达i的最小时间
int prev[5010][5010];
stack<int> sta;
//dp[i][j]=min(dp[i][j],dp[prev[i]][j-1]+cost)

int main(){
    memset(vis,0,sizeof(vis));
    memset(in_degree,0,sizeof(in_degree));
    cin>>n>>m>>T;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            dp[i][j]=INF;
        }
    }
    dp[0][0]=0;
    while(m--){
        int a,b,c;
        cin>>a>>b>>c;
        a--;b--;
        vec[a].push_back(Point(b,c));
        in_degree[b]++;
    }
    int cnt=0;
    while(cnt<n){
        for(int i=0;i<n;i++){
            if(in_degree[i]==0&&!vis[i]){
                que.push(i);
                vis[i]=true;
                cnt++;
                for(int j=0;j<vec[i].size();j++){
                    int to=vec[i][j].to;
                    in_degree[to]--;
                }
            }
        }
    }
    while(!que.empty()){
        int now=que.front();
        que.pop();
        for(int i=0;i<vec[now].size();i++){
            int to=vec[now][i].to;
            int cost=vec[now][i].cost;
            for(int j=1;j<n;j++){
                if(dp[now][j-1]+cost<dp[to][j]){
                    dp[to][j]=dp[now][j-1]+cost;
                    prev[to][j]=now;
                }
            }
        }
    }
    int max_num=0;
    for(int i=0;i<n;i++){
        if(dp[n-1][i]<=T){
            max_num=max(max_num,i);
        }
    }
    cout<<max_num+1<<endl;
    int now=n-1;
    sta.push(now);
    while(now){
        sta.push(prev[now][max_num]);
        now=prev[now][max_num];
        max_num--;
    }
    while(!sta.empty()){
        cout<<sta.top()+1;
        sta.pop();
        if(sta.empty()) cout<<endl;
        else cout<<' ';
    }
}

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页