今天帮舍友做道笔试题,可惜只过了66.7%,怎么看算法都没有问题,后来想想应该是超时了。
题目如下:
题目就是给了这么个有向图,然后让你输出总共有几条链,并且输出最长的链的长度。
我当时想直接DFS统计,从入度为0开始统计,直到叶子节点结束,这是链的个数,最长路顺路就记了。
但是应该是超时了,虽然看不到返回结果,因为我觉得代码没问题。
之前这样写的:
#include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; typedef long long ll; const int maxn = 1e5 + 50; vector<int> g[maxn]; int in[maxn]; ll cost[maxn]; int cnt = 0; ///有几个叶子节点,就有几条链路 ll ans = 0; void dfs(int u, int fa, ll sum) { if(g[u].size() == 0) ///到达叶子节点 { cnt++; ans = max(ans, sum); } for(int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if(v == fa) continue; dfs(v, u, sum + cost[v]); } } int main() { int n, m; scanf("%d %d", &n, &m); for(int i = 1; i <= n; i++) scanf("%lld", &cost[i]); memset(in, 0, sizeof(in)); for(int i = 1; i <= m; i++) { int u, v; scanf("%d %d", &u, &v); g[u].push_back(v); in[v]++; } for(int i = 1; i <= n; i++) { if(!in[i]) { dfs(i, -1, cost[i]); } } printf("%d %lld ", cnt, ans); return 0; } /* 5 4 3 2 10 5 7 1 2 3 1 2 5 4 5 */
超时的可能就是这种树。
会导致一直遍历$2->6->7->8$这条路,所以我们可以遍历一次这条路,然后记录一下就可以了。
#include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; typedef long long ll; const int maxn = 1e6 + 50; vector<int> g[maxn]; int in[maxn]; ll cost[maxn]; int vis[maxn]; ll maxtimes[maxn]; ///从每个节点往下的最长时长 int maxcnt[maxn]; ///从这个节点往下的最长长度 void dfs(int u, int fa) { if(vis[u]) { return; } vis[u] = 1; if(g[u].size() == 0) { maxcnt[u] = 1; maxtimes[u] = cost[u]; return; } for(int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if(v == fa) continue; dfs(v, u); maxcnt[u] += maxcnt[v]; maxtimes[u] = max(maxtimes[u], maxtimes[v]); } maxtimes[u] += cost[u]; } int main() { int n, m; scanf("%d %d", &n, &m); for(int i = 1; i <= n; i++) scanf("%lld", &cost[i]); memset(in, 0, sizeof(in)); memset(vis, 0, sizeof(vis)); memset(maxtimes, 0, sizeof(maxtimes)); memset(maxcnt, 0, sizeof(maxcnt)); for(int i = 1; i <= m; i++) { int u, v; scanf("%d %d", &u, &v); g[u].push_back(v); in[v]++; } int cnt = 0; ll ans = 0; for(int i = 1; i <= n; i++) { if(!in[i]) { dfs(i, -1); cnt += maxcnt[i]; ans = max(ans, maxtimes[i]); } } printf("%d %lld ", cnt, ans); return 0; } /* 5 4 3 2 10 5 7 1 2 1 3 2 5 4 5 6 5 1 2 3 4 5 6 1 2 3 2 2 4 2 5 5 6 */
没给舍友拿全分,不开心 ̄へ ̄