最长路

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\n", res);
for(int i = 1; i <= res; i++) {
    if(i == 1) printf("%d", ant[i]);
    else printf(" %d", ant[i]);
}
printf("\n");

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\n", cnt);
for(int i = cnt - 1; i >= 0; i--) {
    if(i == cnt - 1) printf("%d", ant[i]);
    else printf(" %d", ant[i]);
}
printf("\n");

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

 

posted @ 2019-04-03 20:43  downrainsun  阅读(257)  评论(0编辑  收藏  举报