zoukankan      html  css  js  c++  java
  • 「CF650E」Clockwork Bomb

    传送门
    Luogu

    解题思路

    显然对于两棵树共有的边,我们不会动它。
    考虑第二颗树中有和第一棵树不同的边怎么处理。
    我们设 (fa_1[u],fa_2[u]) 分别代表 (u) 在两棵树中的父亲。
    很显然的想法就是对于第一棵树中的边 (fa_1[u] ightarrow u) 没有出现在第二棵树上,那就把这条边换成 (fa_2[u] ightarrow u)
    但是我们会发现有可能 (fa_2[u] ightarrow u) 已经被连上了。
    那么我们就尝试跳 (fa_2[u]) 的父亲知直到可以连边,这个过程可以用一个并查集来搞(预处理出每个点会连向哪个点)。
    并且在dfs的过程中先处理子树信息,可以保证不会连出环。

    细节注意事项

    • 咕咕咕

    参考代码

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <cctype>
    #include <cmath>
    #include <ctime>
    #include <vector>
    #define rg register
    using namespace std;
    template < typename T > inline void read(T& s) {
     	s = 0; int f = 0; char c = getchar();
     	while (!isdigit(c)) f |= (c == '-'), c = getchar();
     	while (isdigit(c)) s = s * 10 + (c ^ 48), c = getchar();
     	s = f ? -s : s;
    }
    
    const int _ = 500000 + 10;
    
    int n, ff[2][_], fa[_];
    vector < int > G[2][_];
    struct node{ int a, b, c, d; };
    vector < node > ans;
    
    inline int findd(int x) { return fa[x] == x ? x : findd(fa[x]); }
    
    inline void dfs(int x, int u, int f) {
    	for (rg int v : G[x][u]) {
    		if (v == f) continue;
    		ff[x][v] = u, dfs(x, v, u);
    	}
    }
    
    inline void dfss(int u, int f) {
    	for (rg int v : G[0][u]) {
    		if (v == f) continue; dfss(v, u);
    		if (u != ff[1][v] && v != ff[1][u])
    			ans.push_back((node) { v, u, findd(v), ff[1][findd(v)] });
    	}
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
    	freopen("in.in", "r", stdin);
    #endif
    	read(n);
    	for (rg int u, v, i = 1; i < n; ++i) read(u), read(v), G[0][u].push_back(v), G[0][v].push_back(u);
    	for (rg int u, v, i = 1; i < n; ++i) read(u), read(v), G[1][u].push_back(v), G[1][v].push_back(u);
    	dfs(0, 1, 0);
    	dfs(1, 1, 0);
    	for (rg int i = 2; i <= n; ++i) {
    		int u = ff[1][i];
    		if (u == ff[0][i] || i == ff[0][u])
    			fa[i] = u;
    		else
    			fa[i] = i;
    	}
    	dfss(1, 0);
    	printf("%d
    ", (int) ans.size());
    	for (rg node x : ans) printf("%d %d %d %d
    ", x.a, x.b, x.c, x.d);
    	return 0;
    }
    

    完结撒花 (qwq)

  • 相关阅读:
    自学人工智能之数学篇,数学入门并不难
    2018-8-10-win10-uwp-使用资源在后台创建控件
    2019-9-2-win10-uwp-弹起键盘不隐藏界面元素
    2019-7-31-程序猿修养-日志应该如何写
    2018-11-19-WPF-在image控件用鼠标拖拽出矩形
    2019-8-31-C#-如何给-ValueTuple-返回值添加注释
    2019-11-12-浅谈-Windows-桌面端触摸架构演进
    2018-8-10-win10-uwp-打开文件管理器选择文件
    2018-8-10-win10-uwp-验证输入-自定义用户控件
    2019-8-31-dotnet-特性-DynamicallyInvokable-是用来做什么的
  • 原文地址:https://www.cnblogs.com/zsbzsb/p/11746539.html
Copyright © 2011-2022 走看看