AcWing
  • 首页
  • 题库
  • 题解
  • 分享
  • 问答
  • 活动
  • 应用
  • 吐槽
  • 登录/注册

数组和Vector模拟邻接链表+树的直径(两次DFS+树形DP)(学习笔记)

作者: 作者的头像   由比滨结衣 ,  2021-02-22 12:51:18 ,  阅读 31


0


例题网址:

https://www.acwing.com/problem/content/description/1209/

树形DP

用数组模拟

#include <iostream>
#include <cstring>
using namespace std;

const int N = 1e5 + 10;
int h[N], ne[N * 2], e[N * 2], v[N * 2], idx;//无向图,开二倍空间
int d[N];
bool vis[N];
int ans;

void tree_dp(int x){
    vis[x] = true;
    for(int i = h[x]; ~i; i = ne[i]){
        int y = v[i];
        if(vis[y]) continue;
        tree_dp(y);
        ans = max(ans, d[x] + d[y] + e[i]);
        d[x] = max(d[x], d[y] + e[i]);
    }
}

void add(int a, int b, int w){
    e[idx] = w;
    v[idx] = b;
    ne[idx] = h[a];
    h[a] = idx++;
}

int main(){
    int n;
    scanf("%d", &n);
    memset(h, -1, sizeof h);
    for(int i = 0; i < n - 1; i++) {
        int a, b, w;
        scanf("%d%d%d", &a, &b, &w);
        add(a, b, w);
        add(b, a, w);
    }
    tree_dp(1);
    printf("%lld\n", ans * 10 + (ans * (ans + 1ll ) >> 1));
    return 0;
}

用vector模拟

#include <iostream>
#include <cstring>
#include <vector>
using namespace std;

typedef pair<int, long long> pii;

const int N = 1e5 + 10;
long long d[N];
bool vis[N];
long long ans;
vector<pii> city[N];

void tree_dp(int x){
    vis[x] = true;
    for(int i = 0; i < city[x].size(); i++){
        int y = city[x][i].first;
        if(vis[y]) continue;
        tree_dp(y);
        ans = max(ans, d[x] + d[y] + city[x][i].second);
        d[x] = max(d[x], d[y] + city[x][i].second);
    }
}

int main(){
    int n;
    scanf("%d", &n);
    for(int i = 0; i < n - 1; i++) {
        int a, b, w;
        scanf("%d%d%d", &a, &b, &w);
        city[a].push_back({b, w});
        city[b].push_back({a, w});
    }
    tree_dp(1);
    printf("%lld\n", ans * 10 + (ans * (ans + 1ll ) >> 1));
    return 0;
}

两次DFS用结构体存(速度会慢)(还不如用Vector)

#include <iostream>
#include <cstring>
using namespace std;

const int N = 1e5 + 10;
int h[N], idx;//无向图,开二倍空间
int d[N];
bool vis[N];
int ans, maxu;

struct edge{
    int to;
    int ne;
    int w;
}e[N * 2];


void add(int a, int b, int w){
    e[idx].to = b;
    e[idx].ne = h[a];
    e[idx].w = w;
    h[a] = idx++;
}

void dfs(int u, int fa, int w){
    for(int i = h[u]; ~i; i = e[i].ne){
        int j = e[i].to;
        if(j != fa)
            dfs(j, u, w + e[i].w);
    }
    if(ans < w){
        maxu = u;
        ans = w;
    }
}

int main(){
    int n;
    scanf("%d", &n);
    memset(h, -1, sizeof h);
    for(int i = 0; i < n - 1; i++) {
        int a, b, w;
        scanf("%d%d%d", &a, &b, &w);
        add(a, b, w);
        add(b, a, w);
    }
    dfs(1, -1, 0);
    dfs(maxu, -1, 0);
    printf("%lld\n", ans * 10 + (ans * (ans + 1ll ) >> 1));
    return 0;
}

两次DFS用多个数组存(速度更快)

#include <iostream>
#include <cstring>
using namespace std;

const int N = 1e5 + 10;
int h[N], ne[N * 2], e[N * 2], v[N * 2], idx;//无向图,开二倍空间
int d[N];
bool vis[N];
int ans, maxu;

void add(int a, int b, int w){
    e[idx] = w;
    v[idx] = b;
    ne[idx] = h[a];
    h[a] = idx++;
}

void dfs(int u, int fa, int w){
    for(int i = h[u]; ~i; i = ne[i]){
        int j = v[i];
        if(j != fa)
            dfs(j, u, w + e[i]);
    }
    if(ans < w){
        maxu = u;
        ans = w;
    }
}

int main(){
    int n;
    scanf("%d", &n);
    memset(h, -1, sizeof h);
    for(int i = 0; i < n - 1; i++) {
        int a, b, w;
        scanf("%d%d%d", &a, &b, &w);
        add(a, b, w);
        add(b, a, w);
    }
    dfs(1, -1, 0);
    dfs(maxu, -1, 0);
    printf("%lld\n", ans * 10 + (ans * (ans + 1ll ) >> 1));
    return 0;
}

0 评论

你确定删除吗?

© 2018-2021 AcWing 版权所有  |  京ICP备17053197号-1
联系我们  |  常见问题
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标
请输入绑定的邮箱地址
请输入注册信息