首页 > 代码库 > CF-721C DAG图拓扑排序+费用DP

CF-721C DAG图拓扑排序+费用DP

比赛的时候写了个记忆化搜索,超时了。

后来学习了一下,这种题目应该用拓扑排序+DP来做。

dp[][]保存走到[第i个节点][走过j个点]时所用的最短时间。

pre[][]用前驱节点求路径

然后遍历一下dp[n][],求满足t范围的最大下标。

#include <iostream>#include <queue>#include <cstdio>#include <vector>#include <stack>#define N 5050#define INF 1000000200//#define LL long long intusing namespace std;int n,m,sum,cnt,flag,t;int deg[N];vector<int> g[N],f[N];//保存后继节点int dp[N][N],pre[N][N];//保存走到第i个点,走过j个点时所用时间struct cmp{    bool operator()(int a,int b)    {        return a>b;    }};void topoSort(){    priority_queue<int,vector<int>,cmp> q;    for(int i=1;i<=n;i++)        if(deg[i]==0)            q.push(i),deg[i]--;    while(!q.empty())    {        //if(q.size()>1) 可用于判断是否充分排序。        //如果有多个入度为0的同时入队,说明他们之间没有明确的排序条件。        int u=q.top();        q.pop();        sum--;//可用于判断是否有冲突,如果有冲突,就会导致两者或者已上的节点入度无法降为0        for(int i=0;i<g[u].size();i++)        {            int e=g[u][i];            deg[e]--;            for(int j=2;j<=n;j++)            {                //cout<<dp[u][i]<<‘ ‘<<e<<endl;                if(dp[e][j]>dp[u][j-1]+f[u][i])                    dp[e][j]=dp[u][j-1]+f[u][i],pre[e][j]=u;            }        }        for(int i=1;i<=n;i++)            if(deg[i]==0)                q.push(i),deg[i]--;    }}void ini(){    for(int i=0;i<=n;i++)        deg[i]=0,flag=0,g[i].clear(),f[i].clear();    cnt=0,sum=n;    for(int i=0;i<=n;i++)        for(int j=0;j<=n;j++)            dp[i][j]=t+100,pre[i][j]=-1;    dp[1][1]=0;}void add(int u,int v,int fe){    deg[v]++;    g[u].push_back(v);    f[u].push_back(fe);}int main() {    //cin.sync_with_stdio(false);    scanf("%d%d%d",&n,&m,&t);        ini();        for(int i=0;i<m;i++)        {            int u,v,fe;            scanf("%d%d%d",&u,&v,&fe);            add(u,v,fe);        }        //cout<<dp[1][2]<<endl;        topoSort();        int Maxp=-1;        for(int i=1;i<=n;i++)        {            if(dp[n][i]<=t)                Maxp=i;//求最大合法经过点数        }        stack<int> ss;        int pos=n,lef=Maxp;        cout<<Maxp<<endl;        while(pos!=-1)        {            ss.push(pos);            pos=pre[pos][lef],lef--;        }        //ss.push(1);        while(ss.size()>1)            cout<<ss.top()<< ,ss.pop();        cout<<ss.top()<<endl;        ss.pop();        return 0;}

 

CF-721C DAG图拓扑排序+费用DP