zoukankan      html  css  js  c++  java
  • 最长路

    https://vjudge.net/contest/218179#problem/N  题目链接

    一个DAG图有n个点,m条边,走过1条边花费w个时间单位,总共有T时间,问从1到n最多可以经过多少个点?

    最长路用dp,然后拓扑排序,思想差不多

    dp[u][k]表示到u这个点已经经过了k个点。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    using namespace std;
    const int maxm = 5005;
    int n, m, t;
    int res, path[maxm], ant[maxm];
    struct edge {
    int v, w;
    edge(int v = 0, int w = 0) : v(v), w(w) {};
    };
    vector<edge> ve[maxm];
    int dp[maxm][maxm];
    void dfs(int u, int k, int val) {
        if(val < 0) return;
        if(dp[u][k] >= val) return;
        dp[u][k] = val;
        path[k] = u;
        if(u == n) {
            if(k > res) {
                res = k;
                for(int i = 1; i <= k; i++) ant[i] = path[i];
            }
            return;
        }
        for(int i = 0; i < ve[u].size(); i++) {
            int v = ve[u][i].v;
            int w = ve[u][i].w;
            dfs(v, k + 1, val - w);
        }
    }
    
    int main() {
    scanf("%d%d%d", &n, &m, &t);
    int u, v, w;
    while(m--) {
        scanf("%d%d%d", &u, &v, &w);
        ve[u].push_back(edge(v, w));
    }
    res = 0;
    memset(path, 0, sizeof(path));
    memset(dp, -1, sizeof(dp));
    //dp[1][1] = t;
    dfs(1, 1, t);
    printf("%d
    ", res);
    for(int i = 1; i <= res; i++) {
        if(i == 1) printf("%d", ant[i]);
        else printf(" %d", ant[i]);
    }
    printf("
    ");
    
    return 0;
    }

    拓扑排序来更新到v点,中途已经经过k个点的距离,dp数组的含义和上面一样。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<queue>
    using namespace std;
    const int maxm = 5005;
    const int inf = 0x3f3f3f3f;
    int n, m, t;
    int res, ant[maxm], path[maxm][maxm];
    struct edge {
    int v, w;
    edge(int v = 0, int w = 0) : v(v), w(w) {};
    };
    vector<edge> ve[maxm];
    queue<int> q;
    int dp[maxm][maxm];
    int ind[maxm];
    int main() {
    scanf("%d%d%d", &n, &m, &t);
    int u, v, w;
    while(m--) {
        scanf("%d%d%d", &u, &v, &w);
        ve[u].push_back(edge(v, w));
        ind[v]++;
    }
    res = 0;
    memset(path, -1, sizeof(path));
    memset(dp, inf, sizeof(dp));
    dp[1][1] = 0;
    ind[1] = 0;
    for(int i = 1; i <= n; i++) {
        if(ind[i] == 0) q.push(i);
    }
    while(!q.empty()) {
        int now = q.front();
        q.pop();
        for(int i = 0; i < ve[now].size(); i++) {
            int v = ve[now][i].v;
            int w = ve[now][i].w;
            if(--ind[v] == 0) q.push(v);
            for(int j = 2; j <= n; j++) {
                if(dp[now][j - 1] + w < dp[v][j]) {
                    dp[v][j] = dp[now][j - 1] + w;
                    path[v][j] = now;
                }
            }
        }
    }
    int num;
    for(int i = n; i >= 1; i--) {
        if(dp[n][i] <= t) {
            num = i;
            break;
        }
    }
    int cnt = 0;
    for(int i = n, j = num; j > 0; i = path[i][j], j--) {
        ant[cnt++] = i;
    }
    printf("%d
    ", cnt);
    for(int i = cnt - 1; i >= 0; i--) {
        if(i == cnt - 1) printf("%d", ant[i]);
        else printf(" %d", ant[i]);
    }
    printf("
    ");
    
    return 0;
    }

     https://blog.csdn.net/hjt_fathomless/article/details/53024824

    https://blog.csdn.net/West___wind/article/details/52724647

    上面这两个是讲这题的博客。 

    下面几个是专门讲最长路,紫书上讲过这个

    https://blog.csdn.net/jiangpeng59/article/details/56666903

    https://blog.csdn.net/icecab/article/details/80740739

    https://blog.csdn.net/Draven__/article/details/77434566

    https://blog.csdn.net/ccnuacmhdu/article/details/81133637

  • 相关阅读:
    2、函数
    二者取其一(初遇)_网络流
    P1879 [USACO06NOV]玉米田Corn Fields
    P2831 愤怒的小鸟
    P2296 寻找道路
    序(不知道是什么时候的模拟题)
    P2243 电路维修
    P1273 有线电视网
    P2613 【模板】有理数取余
    P1373 小a和uim之大逃离
  • 原文地址:https://www.cnblogs.com/downrainsun/p/10651390.html
Copyright © 2011-2022 走看看