P3629巡逻 树的直径*

news/2024/7/20 22:17:51 标签: 图论, 深度优先, 算法

Link
挺有意思的一道题,思路其实蛮清晰也比较容易理解,然而实现的时候写了半天

代码

const int maxn = 1e6 + 10;
const int maxm = 1e6 + 10;
struct Edge {
    int to, dis, next;
}edge[maxm];
int n, m;
int head[maxn], dis[maxn], cnt = 1;
bool vis[maxn];
void add_edge(int u, int v, int w) {
    cnt++;
    edge[cnt].to = v;
    edge[cnt].dis = w;
    edge[cnt].next = head[u];
    head[u] = cnt;
}
int k;
int fa[maxn];
int now;
void dfs(int cur) {    //now表示目前的最大深度
    vis[cur] = 1;
    for(int i = head[cur]; i; i = edge[i].next) {
        int v = edge[i].to;
        if(vis[v]) continue;
        dis[v] = dis[cur] + edge[i].dis;
        if(dis[v] > dis[now]) {
            now = v;
        }
        fa[v] = i;
        dfs(v);
    }
    vis[cur] = 0;
}
int diam(int s = 1) {
    now = s;
    dfs(s);
    memset(dis, 0, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    memset(fa, 0, sizeof(fa));
    dfs(now);
    return dis[now];
}
void dp(int x) {
    vis[x] = 1;
    for(int i = head[x]; i; i = edge[i].next) {
        int v = edge[i].to;
        if(vis[v]) continue;
        dp(v);
        now = max(now, dis[x] + dis[v] + edge[i].dis);
        dis[x] = max(dis[x], dis[v] + edge[i].dis);
    }
}
/*
int dp(int i) {
    if(vis[i]) return dis[i];
    dis[i] = 0;
    vis[i] = 1;
    for(int j = head[i]; j; j = edge[j].next) {
        int v = edge[j].to;
            dis[i] = max(dis[i], dp(v) + edge[i].dis);
    }
    return dis[i];
}
*/
void solve() {
    cin >> n >> k;
    for(int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        add_edge(u, v, 1);
        add_edge(v, u, 1);
    }
    int len = diam();
    int ans = 2*(n-1)-len+1;
    if(k == 2) {
        while(fa[now]) {
            edge[fa[now]].dis = edge[fa[now]^1].dis = -1;
            now = edge[fa[now] ^ 1].to;
        }
        memset(dis, 0, sizeof(dis));
        memset(vis, 0, sizeof(vis));
        now = 0;
        dp(1);
        int maxx = 0;
        for(int i = 1; i <= n; i++)
            maxx = max(maxx, dis[i]);
//        ans = ans - maxx + 1;
        ans -= now - 1;
    }
    cout << ans << endl;
}

http://www.niftyadmin.cn/n/1764903.html

相关文章

P1099 [NOIP2007 提高组] 树网的核——树的直径

Link 方法蛮多的一道题&#xff0c;主要是在书上看的&#xff0c;这里不想写了&#xff0c;贴个代码保存一下。 代码 // // #include <bits/stdc.h> using namespace std; //#define mp make_pair #define pii pair<int,int> #define pb push_back #define ll lo…

MySQL进口.sql文件和常用命令

MySQL进口.sql文件和常用命令 在MySQL Qurey Brower中直接导入*.sql脚本&#xff0c;是不能一次运行多条sql命令的。在mysql中运行sql文件的命令&#xff1a; mysql> source d:/myprogram/database/db.sql; 另附mysql经常使用命令&#xff1a; 一) 连接MYSQL&#xff1a…

acwing352.闇の連鎖 树上差分

Link 思路 问题转化蛮巧妙的。主要边恰好构成一棵树&#xff0c;考虑只添加一条附加边<x,y>&#xff0c;则恰好构成一个环&#xff0c;如果第一步选择切断x,y之间路径的某条主要边&#xff0c;则第二步必须切断<x,y>&#xff0c;才能分成不连通的两部分。 所以相…

慈溪,她和他的故事!

发发文章&#xff0c;写写感受&#xff0c;一片欣喜&#xff01; 当意外出现 他们措手无策&#xff01; 19岁的小念是宁波某大学的学生,今年暑假留在武汉打临时工,并且和男友一起租了房子,小两口日子过得还有滋有味.只是原本幸福的生活被这突如其来的意外怀孕给打乱了,两人也不…

poj2777 线段树染色

Link 题意 两种操作 1.将[a, b] 改为颜色c 2.询问[a,b] 有几种颜色 初始颜色均为1 很久没做过线段树了&#xff0c;温习一下。 struct SegmentTree {int l, r;int col;int lz; #define l(x) tree[x].l #define r(x) tree[x].r #define col(x) tree[x].col #define lz(x) tre…

Oracle包的概念

转自&#xff1a;http://www.cnblogs.com/lovemoon714/archive/2012/02/29/2373695.html 1、为什么要使用包&#xff1f; 答&#xff1a; 在一个大型项目中&#xff0c;可能有很多模块&#xff0c;而每个模块又有自己的过程、函数等。而这些过程、函数默认是放在一起的&#xf…

P1502 窗口的星星

Link lydp221 思路 一开始没考虑在边界的情况。。不知道为什么ac了。。。 1.矩形边界上的星星不算&#xff0c;可以采用把所有星星向左、下各平移0.5距离&#xff08;因为坐标都是整数&#xff09;&#xff0c;在此基础上&#xff0c;不妨假设圈住星星的矩形顶点坐标都是整数…

socket选项设置

#include <sys/socket.h>int setsockopt( int socket, int level, int option_name, const void *option_value, size_t option_len); 第一个参数socket是套接字描述符。第二个参数level是被设置的选项的级别&#xff0c;如果想要在套接字级别上设置选项&#xff0c;就必…