zoukankan      html  css  js  c++  java
  • CodeForces

    题意:

    n个点m条边的图,起点为1,终点为n,每一条单向边输入格式为:

    a,b,c     //从a点到b点耗时为c

    题目问你最多从起点1到终点n能经过多少个不同的点,且总耗时小于等于t

    题解:

    这道题我原本以为是改一下最短路去做,,,但是想不到怎么写。网上搜了搜,发现是拓扑+dp。

    拓扑排序有啥用?

    比如一共有好多件事情,事情A要再事情B(或者更多)事情做完才能做,也就是给你了一种完成事件的顺序

    那么转化到这道题上就是从1点到其他点有多种方式,它就是按顺序做这些事情(也就是按这个顺序dp)

    那么我看了网上代码后发现,他们都是把1这个点当于没有入度去处理,也就是数据默认1这个点的入度为0

    譬如下面这个数据用在本题代码上就不行:

    4 5 2
    1 2
    3 2
    3 4
    1 3
    4 1

    但是实际画图你会发现1->3->4这条路是可以的

    回归本题dp:

    dp[i][j],到达i点时,观光了j个景点的最小时间
    转移是这样对于一条边u -> v,dp[v][j] = min(dp[v][j],dp[u][j - 1] + dis[u][v]);

    代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <math.h>
     5 #include <string.h>
     6 #include <queue>
     7 #include <set>
     8 #include <map>
     9 #include <algorithm>
    10 using namespace std;
    11 const int maxn=5005;
    12 const int inf=0x3f3f3f3f;
    13 int vin[maxn];
    14 struct edge
    15 {
    16     int v;
    17     int cost;
    18     edge(int a,int b)
    19     {
    20         v=a,cost=b;
    21     }
    22 };
    23 typedef vector<edge> vec;
    24 vec e[maxn];
    25 int n,m,t;
    26 struct node
    27 {
    28     int per;
    29     int use;
    30 } dp[maxn][maxn];
    31 void tp()
    32 {
    33     queue<int>q;
    34     for(int i=1; i<=n; i++)
    35         if(vin[i]==0)
    36             q.push(i);
    37     while(!q.empty())
    38     {
    39         int u=q.front();
    40         q.pop();
    41         for(int i=0; i<e[u].size(); i++)
    42         {
    43             int v=e[u][i].v;
    44             int cost=e[u][i].cost;
    45             vin[v]--;
    46             if(vin[v]==0)
    47                 q.push(v);
    48             for(int j=1; j<=n; j++)
    49                 if(dp[v][j].use>dp[u][j-1].use+cost)
    50                 {
    51                     dp[v][j].use=dp[u][j-1].use+cost;
    52                     dp[v][j].per=u;
    53                 }
    54         }
    55     }
    56 }
    57 void show(int i,int j)
    58 {
    59     if(dp[i][j].per==-1)
    60     {
    61         printf("1 ");
    62         return;
    63     }
    64     show(dp[i][j].per,j-1);
    65     printf("%d ",i);
    66 }
    67 int main()
    68 {
    69     cin>>n>>m>>t;
    70     int a,b,c;
    71     for(int i=0; i<=n; i++)
    72         for(int j=0; j<=n; j++)
    73         {
    74             dp[i][j].use=inf;
    75         }
    76     memset(vin,0,sizeof(vin));
    77     for(int i=0; i<m; i++)
    78     {
    79         scanf("%d%d%d",&a,&b,&c);
    80         e[a].push_back(edge(b,c));
    81         vin[b]++;
    82     }
    83     dp[1][1].use=0;
    84     dp[1][1].per=-1;
    85     tp();
    86     for(int i=n; i>=1; i--)
    87     {
    88         if(dp[n][i].use<=t)
    89         {
    90             printf("%d
    ",i);
    91             show(n,i);
    92             return 0;
    93         }
    94     }
    95     return 0;
    96 }
    View Code
  • 相关阅读:
    jenkins+robot_framework的安装与邮件配置
    kali最新版中文乱码破解
    Kali系统安装详细步骤
    ADK安装步骤
    Newman跑接口脚本
    Android手机APP测试之环境搭建
    pytest+allre框架搭建
    Android手机测试环境搭建
    adb电脑桥梁手机步骤以及操作
    Android SDK的安装与环境变量配置
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/12817228.html
Copyright © 2011-2022 走看看