CF #374 div2 C 树状dp

来源:互联网 发布:酷宝数据 作假 编辑:程序博客网 时间:2024/05/29 18:33

题目传送门: http://codeforces.com/contest/721/problem/C


题意: 给n个点,m条边(n,m <= 5000),不存在环,两点之间只有一条边,问从1到n在消耗不超过t的情况下最多能走多少点


思路:dfs+dp,状态转移方程:dp[u][j] = min(dp[u][j],val+dp[v][j-1])


代码:

#include <iostream>#include <algorithm>#include <cstring>#include <stdio.h>#include <string>#include <cmath>#include <queue>using namespace std;#define   lson          l,m,rt<<1#define   rson          m+1,r,rt<<1|1#define   ll            long long#define   ull           unsigned long long#define   mem(n,v)      memset(n,v,sizeof(n))#define   MAX           10010#define   MAXN          5005#define   PI            3.1415927#define   E             2.718281828459#define   opnin         freopen("text.in.txt","r",stdin)#define   opnout        freopen("text.out.txt","w",stdout)#define   clsin         fclose(stdin)#define   clsout        fclose(stdout)const int    INF    =   0x3f3f3f3f;const ll     INFF   =   9223372036854775807;const double pi     =   3.141592653589793;const double inf    =   1e18;const double eps    =   1e-8;const ll     mod    =   1e9+7;const ull    mx     =   133333331;struct edge{    int val,next,to;}edges[MAX];int head[MAX];int cnt = 0;int n,m;ll t;int dp[MAXN][MAXN];int vis[MAX];int son[MAX];int ans[MAXN][MAXN];void init(){    mem(ans,0);    mem(vis,0);    for(int i=0;i<=n;i++)        for(int j=0;j<=n;j++)            dp[i][j] = INF;    cnt = 0;    mem(edges,0);    mem(head,-1);}void addedge(int u,int v,int val){    edges[cnt].val = val;    edges[cnt].to = v;    edges[cnt].next = head[u];    head[u] = cnt++;}void dfs(int u){    son[u] = 0;    if(u == n){        dp[u][1] = 0;        son[u] = 1;    }    vis[u] = 1;    int Max = 0;    for(int i=head[u];i!=-1;i = edges[i].next){        int v = edges[i].to , val = edges[i].val;        if(!vis[v]) dfs(v);        Max = max(Max,son[v]);        for(int j=1+son[v];j>=2;j--){            if(val+dp[v][j-1] < dp[u][j]){                dp[u][j] = val+dp[v][j-1];                ans[u][j] = v;            }        }    }    if(Max) son[u] = Max + 1;}int main(){    cin >> n>> m >> t;    init();    int u,v,val;    for(int i=0;i<m;i++){        scanf("%d %d %d",&u,&v,&val);        addedge(u,v,val);    }    dfs(1);    int Max = 0;    for(int i=n;i>=1;i--){        if(dp[1][i] <= t){            Max = i;            break;        }    }    cout << Max << endl;    int cnt = 0;    for(int i=1;i!=n && cnt < n;i = ans[i][Max+1-cnt]){        cnt++;        printf("%d ",i);    }    cout << n << endl;    return 0;}

0 0
原创粉丝点击