Codeforces 721C: Journey DP+TopSort

Journey

题目链接:

http://codeforces.com/contest/721/problem/C

题意:

有个无环图,图中每条边有个权值(时间),求从点1走到点n途中最多可以经过的点的个数和路径(花费不超过t)

 

题解:

由于边和点都只有5000条,先拓扑排序一下,按tp完后的顺序跑一边DP就行了。

dp[i][j]为以点1为起点,点 i 为终点途经 j 个点所需要的最小花费。

 

代码

#include<stdio.h>
#include<vector>
#include<queue>
using namespace std;
const int N=5001;
const int inf=(1e9)+1;
vector<pair<int,int> >vec[N];
int in[N],poi[N],to[N][N];
int dp[N][N];
queue<int>que;
void solve()
{
  int n,m,u,v,res,w,t;
  scanf("%d%d%d",&n,&m,&t);
  for(int i=1;i<=n;++i)
  vec[i].clear(),in[i]=0;
  while(m--)
  {
    scanf("%d%d%d",&u,&v,&w);
    vec[u].push_back(make_pair(v,w));
    in[v]++;
  }
  while(!que.empty())que.pop();
  for(int i=1;i<=n;++i)
  if(!in[i])que.push(i);
  int tot=0;
  while(!que.empty())
  {
    int f=que.front();
    poi[++tot]=f;
    que.pop();
    for(int i=0;i<vec[f].size();++i)
    {
      v=vec[f][i].first;
      in[v]--;
      if(!in[v])que.push(v);
    }
  }
  for(int i=1;i<=n;++i)
  for(int j=0;j<=n;++j)
  dp[i][j]=inf;
  dp[1][0]=0;
  for(int i=1;i<=n;++i)
  for(int j=0;j<vec[poi[i]].size();++j)
  {
    u=poi[i];
    v=vec[u][j].first;
    w=vec[u][j].second;
    for(int k=0;k<n;++k)
    if(dp[u][k]!=inf&&dp[v][k+1]>dp[u][k]+w)
    dp[v][k+1]=dp[u][k]+w,to[v][k+1]=u;
  }
  res=0;
  for(int i=0;i<=n;++i)
  if(dp[n][i]<=t)res=i;
  tot=0,v=n;
  printf("%d\n",res+1);for(int i=res;i>=1;--i)
  poi[++tot]=to[v][i],v=to[v][i];for(int i=res;i>=1;--i)
  printf("%d ",poi[i]);
  printf("%d\n",n);
}
int main()
{
  solve();
  return 0;
}




posted @ 2016-10-27 20:47  kiuhghcsc  阅读(176)  评论(0编辑  收藏  举报