最长路
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