CF-721C DAG图拓扑排序+费用DP
Posted Luke_Ye
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 int using 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的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 919D Substring ( 拓扑排序 && DAG上的DP )