【CF】196 Div.2 D. Book of Evil
2015-07-11 20:47
477 查看
显然这个图是一课树,看着题目首先联想到LCA(肯定是可以解的)。但是看了一下数据大小,应该会TLE。
然后,忽然想到一个前面做过的题目,大概是在一定条件下树中某结点旋转成为根后查询最长路径。
结果灵感就来了,主要思路是对于每个结点,第一次dfs得到两个变量到P结点的最大值以及次大值。
然后,第二次dfs对于当前结点u,u到它的子树中P类结点的最大距离已知(nd[u].mx),那么除u的其他结点v到P类结点的最大距离加上v到u的距离和的最大值为pmx,可以通过每次深搜计算出来,只要d大于等于两者的最大值就为有效结点。而pmx的求法也很容易,对于u来说pmx可能为其父亲的pmx+1,或者为v的兄弟结点的mx值。
刚好因为我们已知每个结点的最大值以及次大值,所有兄弟结点的最大值可求。直接用INT_MIN,实现比较容易。
然后,忽然想到一个前面做过的题目,大概是在一定条件下树中某结点旋转成为根后查询最长路径。
结果灵感就来了,主要思路是对于每个结点,第一次dfs得到两个变量到P结点的最大值以及次大值。
然后,第二次dfs对于当前结点u,u到它的子树中P类结点的最大距离已知(nd[u].mx),那么除u的其他结点v到P类结点的最大距离加上v到u的距离和的最大值为pmx,可以通过每次深搜计算出来,只要d大于等于两者的最大值就为有效结点。而pmx的求法也很容易,对于u来说pmx可能为其父亲的pmx+1,或者为v的兄弟结点的mx值。
刚好因为我们已知每个结点的最大值以及次大值,所有兄弟结点的最大值可求。直接用INT_MIN,实现比较容易。
/* 337D */ #include <iostream> #include <string> #include <map> #include <queue> #include <set> #include <stack> #include <vector> #include <deque> #include <algorithm> #include <cstdio> #include <cmath> #include <ctime> #include <cstring> #include <climits> #include <cctype> #include <cassert> #include <functional> #include <iterator> #include <iomanip> using namespace std; //#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int> #define stpii set<pair<int, int> > #define mpii map<int,int> #define vi vector<int> #define pii pair<int,int> #define vpii vector<pair<int,int> > #define rep(i, a, n) for (int i=a;i<n;++i) #define per(i, a, n) for (int i=n-1;i>=a;--i) #define clr clear #define pb push_back #define mp make_pair #define fir first #define sec second #define all(x) (x).begin(),(x).end() #define SZ(x) ((int)(x).size()) #define lson l, mid, rt<<1 #define rson mid+1, r, rt<<1|1 typedef struct { int mx, mx2; } node_t; const int maxn = 1e5+5; bool mark[maxn]; int n, m, d; vi E[maxn]; node_t nd[maxn]; int ans = 0; int dfs(int u, int fa) { int i, v; int tmp; nd[u].mx = nd[u].mx2 = INT_MIN; if (mark[u]) nd[u].mx = 0; for (i=0; i<SZ(E[u]); ++i) { v = E[u][i]; if (v != fa) { tmp = dfs(v, u) + 1; if (tmp >= nd[u].mx) { // find the two fathest distance from p[*] to u nd[u].mx2 = nd[u].mx; nd[u].mx = tmp; } else if (tmp > nd[u].mx2) { nd[u].mx2 = tmp; } } } // -1 means no p in the path return nd[u].mx; } void dfs2(int u, int fa, int pmx) { int i, v; int tmp = max(pmx, nd[u].mx); if (tmp <= d) { ++ans; } for (i=0; i<SZ(E[u]); ++i) { v = E[u][i]; if (v != fa) { if (nd[v].mx+1 == nd[u].mx) tmp = nd[u].mx2; else tmp = nd[u].mx; tmp = max(tmp, pmx)+1; dfs2(v, u, tmp); } } } int main() { ios::sync_with_stdio(false); #ifndef ONLINE_JUDGE freopen("data.in", "r", stdin); freopen("data.out", "w", stdout); #endif int u, v; scanf("%d %d %d", &n, &m, &d); while (m--) { scanf("%d", &u); mark[u] = true; } rep(i, 1, n) { scanf("%d %d", &u, &v); E[u].pb(v); E[v].pb(u); } // get the item in node dfs(1, -1); // calculate the number of valid position dfs2(1, -1, INT_MIN); printf("%d\n", ans); #ifndef ONLINE_JUDGE printf("time = %d.\n", (int)clock()); #endif return 0; }
相关文章推荐
- 1009. 说反话 (20)
- POJ 3159 Candies(差分约束 转spfa+stack 求最短路径)
- c语言
- 【计蒜客系列】挑战难题3:判断质数
- Linux CentOS下shell显示-bash-4.1$不显示用户名路径
- [LeetCode]4Sum
- 1008. 数组元素循环右移问题 (20)
- 鼠标钩子 键盘钩子
- WPF动画
- 7月流水一日
- 设计模式之适配器模式
- 线性表链式存储设计与实现 - API实现
- 线性表链式存储设计与实现 - API实现
- 浅谈双连通分量、强连通分量
- 树链剖分
- hdu2222Keywords Search (特里)
- java基础——“”equals“”与 “”==“” 的区别
- 用缓动函数模时钟
- 1007. 素数对猜想 (20)
- PHP底层的运行机制与原理