CodeForces 721C Journey(拓扑排序+DP)
<题目链接>
题目大意:
一个DAG图有n个点,m条边,走过每条边都会花费一定的时间,问你在不超过T时间的条件下,从1到n点最多能够经过几个节点。
解题分析:
对这个有向图,我们进行拓扑排序,并且在拓扑排序的过程中,用dp来进行状态的转移,$dp[i][j]$表示,在以$i$为终点的且经过$j$个点的路径中,所花的最少时间。
#include <bits/stdc++.h> using namespace std; #define pb push_back const int N = 5e3+5; int dp[N][N],path[N][N],indeg[N]; bool vis[N]; int n,m,T; struct Edge{ int to,val; }; vector<Edge>G[N]; inline void Toposort(){ queue<int>q; memset(dp,0x3f,sizeof(dp)); dp[1][1]=0; for(int i=1;i<=n;i++) if(!indeg[i]){ vis[i]=true;q.push(i); } while(!q.empty()){ int u=q.front();q.pop(); vis[u]=true; for(int i=0;i<G[u].size();i++){ int v=G[u][i].to,cost=G[u][i].val; if(indeg[v]){ --indeg[v]; for(int j=2;j<=n;j++){ //拓扑排序的过程中进行状态的转移 if(dp[v][j]>dp[u][j-1]+cost){ dp[v][j]=dp[u][j-1]+cost; path[v][j]=u; //记录转移到该状态的节点 } } } if(!indeg[v])q.push(v); } } } void Output(int now,int num){ //输出路径 if(now==1){ printf("%d",now);return; } Output(path[now][num],num-1); printf(" %d",now); } inline void Print(){ int res=0; for(int i=n;i>=1;i--){ if(dp[n][i]<=T){ res=i; break; } }printf("%d\n",res); if(res)Output(n,res); puts(""); } int main(){ scanf("%d%d%d",&n,&m,&T); for(int i=1;i<=m;i++){ int u,v,w;scanf("%d%d%d",&u,&v,&w); G[u].pb(Edge{v,w}); indeg[v]++; } Toposort(); Print(); }
作者:is_ok
出处:http://www.cnblogs.com/00isok/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。