一道阿里笔试题

今天帮舍友做道笔试题,可惜只过了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\n", cnt, ans);
    return 0;
}
/*
5 4
3
2
10
5
7
1 2
3 1
2 5
4 5

*/
Code

超时的可能就是这种树。

会导致一直遍历$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\n", 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
*/
Code

没给舍友拿全分,不开心 ̄へ ̄

posted @ 2018-08-04 20:34  卷珠帘  阅读(280)  评论(0编辑  收藏  举报