求树的直径

class Solution {
public:
    static const int maxn = 20;
    int head[maxn], to[maxn<<1], nex[maxn<<1], tot;
    void init() {
        memset(head, -1, sizeof(head));
        tot = 0;
    }
    void add(int x, int y) {
        to[tot] = y;
        nex[tot] = head[x];
        head[x] = tot++;
    }
    bool is[maxn], vis[maxn];
    int dis[maxn], maxd;//最长距离maxd
    int bfs(int u) {
        queue<int> que;
        while (!que.empty()) que.pop();
        memset(vis, 0, sizeof(vis));
        memset(dis, 0, sizeof(dis));
        que.push(u);
        int max_num = 0;
        maxd = 0;
        while (!que.empty()) {
            int now = que.front(); que.pop();
            vis[now] = 1;
            for (int i = head[now]; ~i; i = nex[i]) {
                int v = to[i];
                if(vis[v] || !is[v]) continue;
                vis[v] = 1;
                dis[v] = dis[now] + 1;
                if(dis[v] > maxd) {
                    maxd = dis[v];
                    max_num = v;
                }
                que.push(v);
            }
        }
        return max_num;
    }
    vector<int> countSubgraphsForEachDiameter(int n, vector<vector<int>>& edges) {
        int ans[20];
        init();
        memset(ans, 0, sizeof(ans));
        for (int i = 0; i < edges.size(); i++) {
            int u = edges[i][0], v = edges[i][1];
            add(u, v);
            add(v, u);
        }
        for (int i = 3; i < (1<<n); i++) {
            int cnt = 0, pos;
            for (int j = 1; j <= n; j++) is[j] = 0;
            for (int j = 0; j < n; j++) {
                if(((i>>j)&1)) is[j + 1] = 1, cnt++, pos = j + 1;
            }
            int u = bfs(pos);
            int s = bfs(u);
            int tmp = 0;
            for (int j = 1; j <= n; j++) if(vis[j]) tmp++;
            if(tmp == cnt) ans[maxd]++;
        }
        vector<int> xx;
        for (int i = 1; i < n; i++)
            xx.push_back(ans[i]);
        return xx;
    }
}pp;
//树形dp可以处理负权,两遍bfs和dfs不能,但可以输出路径,而dp不行
//树形dp,找路径带权树上最长的路径长度
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 7;
typedef long long ll;
int head[maxn], to[maxn<<1], nex[maxn<<1], tot, edge[maxn<<1], vis[maxn];
int dp[maxn];
void add(int x, int y, int z) {
    to[tot] = y;
    edge[tot] = z;
    nex[tot] = head[x];
    head[x] = tot++;
}
int ans;
void dfs(int x) {
    vis[x] = 1;
    for (int i = head[x]; ~i; i = nex[i]) {
        int v = to[i];
        if(vis[v]) continue;
        dfs(v);
        ans = max(ans, dp[v] + dp[x] + edge[i]);
        dp[x] = max(dp[x], dp[v] + edge[i]);
    }
}
int main()
{
    memset(head, -1, sizeof(head));
    int n;
    scanf("%d", &n);
    for (int i = 1; i < n; i++) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        add(u, v, w); add(u, v, w);
    }
    dfs(1);
    printf("%lld\n", (ll)(11 + 10 + ans) * ans / 2);
}
两遍bfs求最长距离,第一遍求出最长的路径上的一个点,第二遍从这个点出发一定是最长的路径
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 7;
typedef long long ll;
int head[maxn], to[maxn<<1], nex[maxn<<1], tot, edge[maxn<<1], vis[maxn];
int dis[maxn], maxd;//最长距离maxd
void add(int x, int y, int z) {
    to[tot] = y;
    edge[tot] = z;
    nex[tot] = head[x];
    head[x] = tot++;
}
int bfs(int u) {
    queue<int> que;
    while (!que.empty()) que.pop();
    memset(vis, 0, sizeof(vis));
    memset(dis, 0, sizeof(dis));
    que.push(u);
    int max_num = 0;
    maxd = 0;
    while (!que.empty()) {
        int now = que.front(); que.pop();
        vis[now] = 1;
        for (int i = head[now]; ~i; i = nex[i]) {
            int v = to[i];
            if(vis[v]) continue;
            vis[v] = 1;
            dis[v] = dis[now] + edge[i];
            if(dis[v] > maxd) {
                maxd = dis[v];
                max_num = v;
            }
            que.push(v);
        }
    }
    return max_num;
}
int main()
{
    memset(head, -1, sizeof(head));
    int n;
    scanf("%d", &n);
    for (int i = 1; i < n; i++) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        add(u, v, w); add(v, u, w);
    }
    int u = bfs(1);//第一遍求出的最长路径上的一个点
    int s = bfs(u);//
    printf("%lld\n", (ll)(11 + 10 + maxd) * maxd / 2);
}
算法竞赛之路 文章被收录于专栏

整理、记录算法竞赛的好题

全部评论

相关推荐

牛客刘北:如果暑期实习是27届的话,你要晚一年才会毕业,企业为什么会等你呢?要搞清时间逻辑呀!27届现在实习只能是在暑假实习,这是日常实习,不是暑期实习。所以多去投日常实习吧,暑期实习肯定不会要你的
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务