【HDU 4812】D Tree【树的分治】
来源:互联网 发布:淘宝买恒压阀被警察抓 编辑:程序博客网 时间:2024/06/04 20:43
题意:给出一棵树,让你寻找一条路径,使得路径上的点相乘mod10^6+3等于k,输出路径的两个端点,按照字典序最小输出。
思路:这类问题很容易想到树的分治,每次找出树的重心,以重心为根,将树分成若干棵子树,然后对于每棵子树再一样的操作,现在就需要求一重心为根,寻找路径,依次遍历每一个子树,然后记录子树中点到根的权值的乘积X,然后通过在哈希表中寻找K×逆元(x),看是否存在,存在则更新答案。
#pragma comment(linker,"/STACK:102400000,102400000")#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define mod 1000003#define N 100005typedef long long ll;struct E{ int v, d, ne; E() {} E(int _v, int _ne):v(_v), ne(_ne){}}e[N*2];bool vis[N];int size, head[N], ans[2], root, flag[mod], F[mod], sum[N], mi, cr, id[N];ll val[N], ni[mod], path[N];void init() { size = 0; memset(vis, false, sizeof(vis)); memset(ans, -1, sizeof(ans)); memset(head, -1, sizeof(head)); memset(flag, 0, sizeof(flag));}void add(int u, int v) { e[size] = E(v, head[u]); head[u] = size++;}void dfs(int u, ll k) { int i, v; sum[u] = 1; vis[u] = true, id[cr] = u; path[cr++] = k*val[u]%mod; ll tm = path[cr-1]; for (i = head[u];~i;i = e[i].ne) { v = e[i].v; if (vis[v]) continue; dfs(v, tm); sum[u] += sum[v]; } vis[u] = false;}ll k;int n, ca;void getans(int a, int b) { if (a > b) swap(a,b); if (ans[0] == -1 || ans[0] > a) ans[0] = a, ans[1] = b; else if (ans[0] == a && ans[1] > b) ans[1] = b;}void getroot(int u) { int i, v, mx = 0; sum[u] = 1; vis[u] = true; for (i = head[u];~i;i = e[i].ne) { v = e[i].v; if (vis[v]) continue; getroot(v); sum[u] += sum[v]; mx = max(mx, sum[v]); } mx = max(mx, sum[0]-sum[u]); if (mx < mi) mi = mx, root = u; vis[u] = false;}void cal(int u, int cnt) { if (cnt == 1) return; int i, v, j; mi = n; sum[0] = cnt; getroot(u); vis[root] = true; for (i = head[root];~i;i = e[i].ne) { v = e[i].v; if (vis[v]) continue; cr = 0; dfs(v, 1); for (j = 0;j < cr;j++) { if (path[j]*val[root]%mod == k) getans(root, id[j]); ll tm = k*ni[path[j]*val[root]%mod]%mod; if (flag[tm] != ca) continue; getans(F[tm], id[j]); } for (j = 0;j < cr;j++) { int tm = path[j]; if (flag[tm] != ca || F[tm] > id[j]) F[tm] = id[j], flag[tm] = ca; } } ca++; for (i = head[root];~i;i = e[i].ne) { if (vis[e[i].v]) continue; cal(e[i].v, sum[e[i].v]); }}ll egcd(ll a,ll b, ll &x, ll &y) {//得到的是a*x+b*y=gcd(a,b)ll temp,tempx;if (b == 0) {x = 1;y = 0;return a;}temp = egcd(b,a % b, x, y);tempx = x;x = y;y = tempx - a / b * y;return temp;}int main() { int u, v, i, j; ll y; for (i = 0;i < mod;i++) { egcd(i*1ll, mod*1ll, ni[i], y); ni[i] %= mod, ni[i] = (ni[i]+mod)%mod; } while (~scanf("%d%I64d", &n, &k)) { init(); ca = 1; for (i = 1;i <= n;i++) scanf("%I64d", &val[i]); for (i = 1;i < n;i++) { scanf("%d%d", &u, &v); add(u, v), add(v, u); } cal(1, n); if (ans[0] == -1) puts("No solution"); else printf("%d %d\n", ans[0], ans[1]); }}
0 0
- 【HDU 4812】D Tree【树的分治】
- HDU 4812 D Tree(树分治)
- HDU 4812 D Tree [树分治]
- hdu 4812 D Tree 树的点分治
- HDU 4812 D Tree 树的点分治
- hdu 4812 D Tree(树的点分治)
- hdu 4812 D Tree(分治)
- HDU 4812 D Tree (树分治之点分治)
- 【HDU】4812 D Tree 点分治
- HDU 4812 D Tree 点分治
- [HDOJ 4812][Vjudge 48318] D Tree [树的分治]
- [树的点分治] [HDU4812] D Tree
- 【树分治】 HDOJ 4812 D Tree
- HDU 4812 D Tree (树上点分治)
- HDU 4812 D Tree 点分治 + 逆元
- HDU 4812 D Tree 树分治+逆元+hash新姿势
- HDU 4812 D Tree (2013-南京 树分治 + 逆元 + 离散化)
- hdu 4812 D Tree
- C++ 重写重载重定义区别
- SQL Server 可更新订阅中有行筛选的同步复制移除项目而不重新初始化所有订阅!
- Swift编程语言学习12 ——实例方法(Instance Methods)和类型方法(Type Methods)
- 仇恨的力量
- 青岛热死了
- 【HDU 4812】D Tree【树的分治】
- 杭电4548 好长的筛选素数,打表,细节特别要注意l代表后面的大的那个数
- 三个方法让你成为更好的程序员
- hdu 2005第几天 函数 20140725.cpp
- hdu 2006 奇数乘积
- 单硬盘上mac + win7双系统,GUID-GPT分区
- 设计模式——责任链(ChainOfResponsibility)学习笔记
- 14072500837-hd-素数判定.cpp
- 关于内表更新方式的速度问题