首页 > 代码库 > 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
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。