ZOJ 3820 2014ACM/ICPC牡丹江司B称号
3797714 2014 - 10 - 12 21:58 : 19
Accepted 3820 C++
1350 70240
zz_1215
比較麻烦的一道题吧,開始的时候不停的段异常,后面知道是爆栈了,然后用数组模拟递归,才ac了
思路挺简单的,先找到这个树的直径,单独拿出来,能够证明最后选的两个点一定是在直径上的。我就不证了
然后求出这条直径上的每一个点向外延伸的最远距离
对这个距离做两次RMQ,第一次是对于往左边计算最大距离,所以要这个距离的序列要依次+1,+2,+3.......+n-1,+n
第二次是对于往右边计算最大距离。所以序列要+n,+n-1........+3,+2,+1
然后确定一个左起点。二分右起点
最后的复杂度是O(n*log(n))
实现起来还是挺复杂的,吐槽下这样的考代码能力的题
最后有一点提醒下,向外延伸的时候不要忘了向父节点的方向延伸。由于这个我又wa了一次
- #pragma comment(linker, "/STACK:102400000,102400000")
- #include<iostream>
- #include<vector>
- #include<algorithm>
- #include<cstdio>
- #include<queue>
- #include<stack>
- #include<string>
- #include<map>
- #include<set>
- #include<cmath>
- #include<cassert>
- #include<cstring>
- #include<iomanip>
- using namespace std;
- #ifdef _WIN32
- #define i64 __int64
- #define out64 "%I64d\n"
- #define in64 "%I64d"
- #else
- #define i64 long long
- #define out64 "%lld\n"
- #define in64 "%lld"
- #endif
- /************ for topcoder by zz1215 *******************/
- #define foreach(c,itr) for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
- #define FOR(i,a,b) for( int i = (a) ; i <= (b) ; i ++)
- #define FF(i,a) for( int i = 0 ; i < (a) ; i ++)
- #define FFD(i,a,b) for( int i = (a) ; i >= (b) ; i --)
- #define S64(a) scanf(in64,&a)
- #define SS(a) scanf("%d",&a)
- #define LL(a) ((a)<<1)
- #define RR(a) (((a)<<1)+1)
- #define pb push_back
- #define pf push_front
- #define X first
- #define Y second
- #define CL(Q) while(!Q.empty())Q.pop()
- #define MM(name,what) memset(name,what,sizeof(name))
- #define MC(a,b) memcpy(a,b,sizeof(b))
- #define MAX(a,b) ((a)>(b)?
- (a):(b))
- #define MIN(a,b) ((a)<(b)?(a):(b))
- #define read freopen("out.txt","r",stdin)
- #define write freopen("out2.txt","w",stdout)
- const int inf = 0x3f3f3f3f;
- const i64 inf64 = 0x3f3f3f3f3f3f3f3fLL;
- const double oo = 10e9;
- const double eps = 10e-9;
- const double pi = acos(-1.0);
- const int maxn = 211111;
- struct Node{
- int now;
- int to;
- int h;
- bool operator < (const Node & cmp) const{
- return h>cmp.h;
- }
- }node;
- int n;
- vector<Node>g[maxn];
- int dfv[maxn];
- int dfn[maxn];
- int t[maxn];
- int h[maxn];
- int df;
- vector<int>s;
- vector<int>si;
- bool vis[maxn];
- vector<int>line;
- int a[maxn];
- int ax[maxn][20];
- int dx[maxn][20];
- int lg2[maxn];
- bool isline[maxn];
- void dfs(){
- for (int i = 1; i <= n; i++){
- vis[i] = false;
- }
- df = 1;
- s.clear();
- si.clear();
- s.push_back(1);
- si.push_back(0);
- vis[1] = true;
- int now, to, id;
- while (!s.empty()){
- now = s.back();
- id = si.back();
- if (id < g[now].size()){
- to = g[now][id].to;
- si.back()++;
- if (!vis[to]){
- vis[to] = true;
- t[to] = now;
- s.push_back(to);
- si.push_back(0);
- }
- }
- else{
- dfv[df] = s.back();
- dfn[s.back()] = df++;
- s.pop_back();
- si.pop_back();
- }
- }
- }
- int find_len(int now){
- if (g[now].size() >= 2){
- return g[now][0].h + g[now][1].h;
- }
- else if (g[now].size() == 1){
- return g[now][0].h;
- }
- else{
- return 0;
- }
- }
- void get_line(int now){
- if (g[now].size() >= 2){
- int t1 = g[now][0].to;
- int t2 = g[now][1].to;
- isline[now] = true;
- while (true){
- isline[t1] = true;
- line.push_back(t1);
- if (g[t1].size() > 0){
- t1 = g[t1][0].to;
- }
- else{
- break;
- }
- }
- reverse(line.begin(), line.end());
- line.push_back(now);
- while (true){
- isline[t2] = true;
- line.push_back(t2);
- if (g[t2].size() > 0){
- t2 = g[t2][0].to;
- }
- else{
- break;
- }
- }
- }
- else if(g[now].size() ==1){
- while (true){
- isline[now] = true;
- line.push_back(now);
- if (g[now].size() > 0){
- now = g[now][0].to;
- }
- else{
- break;
- }
- }
- }
- }
- int max_way(int now){
- int to;
- int re = 0;
- for (int i = 0; i < g[now].size(); i++){
- to = g[now][i].to;
- if (!isline[to]){
- re = max(re, g[now][i].h);
- }
- }
- return re;
- }
- void sparse_table(){
- for (int i = 0; i < line.size(); i++){
- ax[i][0] = a[i]+i;
- dx[i][0] = a[i]+(int)line.size()-1-i;
- }
- for (int step = 1; (1 << step) < line.size(); step++){
- for (int i = 0; i < line.size(); i++){
- ax[i][step] = ax[i][step - 1];
- dx[i][step] = dx[i][step - 1];
- if (i + (1 << (step - 1)) < line.size()){
- ax[i][step] = max(ax[i][step], ax[i + (1 << (step - 1))][step - 1]);
- dx[i][step] = max(dx[i][step], dx[i + (1 << (step - 1))][step - 1]);
- }
- }
- }
- }
- int max_a(int l, int r){
- return max(ax[l][lg2[r - l + 1]], ax[r - (1 << lg2[r - l + 1]) + 1][lg2[r - l + 1]]);
- }
- int max_d(int l, int r){
- return max(dx[l][lg2[r - l + 1]], dx[r - (1 << lg2[r - l + 1]) + 1][lg2[r - l + 1]]);
- }
- int find(int l, int r){
- int mid = (r + l) / 2;
- return max(max_a(l, mid) - l, max_d(mid+1,r)-( (int)line.size()-1-r ) );
- }
- int back[maxn];
- void find_back(){
- for (int i = 1; i <= n; i++){
- back[i] = 0;
- }
- queue<int>q;
- q.push(1);
- int now, to,fa,temp;
- while (!q.empty()){
- now = q.front();
- q.pop();
- if (t[now]){
- fa = t[now];
- back[now] = 1 + back[fa];
- temp = 0;
- if (g[fa][0].to == now){
- if (g[fa].size() >= 2){
- temp = g[fa][1].h+1;
- }
- }
- else{
- temp = g[fa][0].h;
- }
- back[now] = max(back[now], temp);
- }
- for (int i = 0; i < g[now].size(); i++){
- q.push(g[now][i].to);
- }
- }
- }
- void start(){
- dfs();
- for (int i = 1; i <= n; i++){
- h[i] = 0;
- }
- vector<Node>gg;
- int now, to;
- for (now = 1; now <= n; now++){
- gg.clear();
- for (int i = 0; i < g[now].size(); i++){
- to = g[now][i].to;
- if (to != t[now]){
- gg.push_back(g[now][i]);
- }
- }
- g[now] = gg;
- }
- for (int x = 1; x < df; x++){
- now = dfv[x];
- for (int i = 0; i < g[now].size(); i++){
- to = g[now][i].to;
- h[now] = max(h[now], h[to] + 1);
- }
- }
- for (now = 1; now <= n; now++){
- for (int i = 0; i < g[now].size(); i++){
- to = g[now][i].to;
- g[now][i].h = h[to] + 1;
- }
- }
- for (now = 1; now <= n; now++){
- sort(g[now].begin(), g[now].end());
- }
- int id;
- int len = -1;
- int temp;
- for (now = 1; now <= n; now++){
- temp = find_len(now);
- if (temp > len){
- len = temp;
- id = now;
- }
- }
- for (int i = 1; i <= n; i++){
- isline[i] = false;
- }
- line.clear();
- get_line(id);
- find_back();
- for (int i = 0; i < line.size(); i++){
- a[i] = max_way(line[i]);
- if (line[i] == id){
- a[i] = max(a[i], back[id]);
- }
- }
- sparse_table();
- int ans=inf;
- int left;
- int right;
- int l, r;
- for (int lend = 0; lend < line.size(); lend++){
- l = lend;
- r = line.size() - 1;
- while (l + 2 < r){
- int mid = (l + r) / 2;
- if (find(lend, mid) > (int)line.size() - 1 - mid){
- r = mid;
- }
- else{
- l = mid;
- }
- }
- for (int x = l; x <= r; x++){
- temp = max(find(lend, x), (int)line.size() - 1 - x);
- temp = max(temp, lend);
- if (temp < ans){
- ans = temp;
- left = lend;
- right = x;
- }
- }
- }
- cout << ans << " " << line[left] << " " << line[right] << endl;
- }
- int main(){
- for (int i = 0; i < 20; i++){
- if ((1 << i) < maxn){
- lg2[1 << i] = i;
- }
- }
- for (int i = 3; i < maxn; i++){
- if (!lg2[i]){
- lg2[i] = lg2[i - 1];
- }
- }
- int T;
- cin >> T;
- while (T--){
- cin >> n;
- for (int i = 1; i <= n; i++){
- g[i].clear();
- }
- node.h = 0;
- for (int i = 1; i <= n - 1; i++){
- // cin >> node.now >> node.to;
- SS(node.now); SS(node.to);
- g[node.now].push_back(node);
- swap(node.now, node.to);
- g[node.now].push_back(node);
- }
- start();
- }
- return 0;
- }
版权声明:本文博客原创文章,博客,未经同意,不得转载。
ZOJ 3820 2014ACM/ICPC牡丹江司B称号的更多相关文章
- ZOJ3819 ACM-ICPC 2014 亚洲区域赛的比赛现场牡丹江司A称号 Average Score 注册标题
Average Score Time Limit: 2 Seconds Memory Limit: 131072 KB Bob is a freshman in Marjar Univers ...
- ZOJ3822 ACM-ICPC 2014 亚洲杯赛事现场牡丹江司D称号Domination 可能性DP
Domination Time Limit: 8 Seconds Memory Limit: 131072 KB Special Judge Edward is the headm ...
- HDU 5127.Dogs' Candies-STL(vector)神奇的题,set过不了 (2014ACM/ICPC亚洲区广州站-重现赛(感谢华工和北大))
周六周末组队训练赛. Dogs' Candies Time Limit: 30000/30000 MS (Java/Others) Memory Limit: 512000/512000 K ( ...
- HDU 5135.Little Zu Chongzhi's Triangles-字符串 (2014ACM/ICPC亚洲区广州站-重现赛)
Little Zu Chongzhi's Triangles Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 512000/512000 ...
- HDU 5131.Song Jiang's rank list (2014ACM/ICPC亚洲区广州站-重现赛)
Song Jiang's rank list Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 512000/512000 K (Java ...
- zoj 3820 Building Fire Stations(二分法+bfs)
题目链接:zoj 3820 Building Fire Stations 题目大意:给定一棵树.选取两个建立加油站,问说全部点距离加油站距离的最大值的最小值是多少,而且随意输出一种建立加油站的方式. ...
- 2014ACM/ICPC亚洲区域赛牡丹江站现场赛-A ( ZOJ 3819 ) Average Score
Average Score Time Limit: 2 Seconds Memory Limit: 65536 KB Bob is a freshman in Marjar Universi ...
- 2014ACM/ICPC亚洲区域赛牡丹江站现场赛-K ( ZOJ 3829 ) Known Notation
Known Notation Time Limit: 2 Seconds Memory Limit: 65536 KB Do you know reverse Polish notation ...
- 2014ACM/ICPC亚洲区域赛牡丹江站现场赛-I ( ZOJ 3827 ) Information Entropy
Information Entropy Time Limit: 2 Seconds Memory Limit: 65536 KB Special Judge Information ...
随机推荐
- HTML与XML关系分析
本来这篇是为CSS准备的,但看到视频中CSS和HTML.XML都有关系,即,都是设置他们的样式.而XML和HTML的格式看着也有些类似,就不得不分析一下二者之间的关系了. 要想分析事物关系,要先弄清他 ...
- POJ 3652 & ZOJ 2934 & HDU 2721 Persistent Bits(数学 元)
主题链接: PKU:http://poj.org/problem?id=3652 ZJU:http://acm.zju.edu.cn/onlinejudge/showProblem.do? probl ...
- JDBC数据库连接
JDBC是什么? Java Data Base Connectivity JDBC是: 以统一方式訪问数据库的API,能够訪问不论什么类型表列数据.特别是存储在关系数据中的数据.JDBC代表Java数 ...
- ajax相关体会
参考原文: 例子:http://blog.csdn.net/beijiguangyong/article/details/7725596 原理讲解:http://www.cnblogs.com/min ...
- hdu 4007 Dave (2011年大连ACM网络赛)
题意:给定正方形的边长 r ,在平面内寻找正方形可以圈住的点的最大的个数. 分析:先对点排序,然后固定一条边,再平移另一条垂直边,得到点的个数,最后比较大小即可. 注意:不包含正方形倾斜的情况! // ...
- OpenCV 编程简单介绍(矩阵/图像/视频的基本读写操作)
PS. 因为csdn博客文章长度有限制,本文有部分内容被截掉了.在OpenCV中文站点的wiki上有可读性更好.而且是完整的版本号,欢迎浏览. OpenCV Wiki :<OpenCV 编程简单 ...
- 关于oracle的备份 导入
****假设要保存为bat文件.最好用汉字 导入: imp clsoftoa/clsoftoa@orcl124 --要导入的数据库的 username/password@数据库名 fromuser= ...
- Install Linux Kernel - AT91SAM9260EK
两.AT91SAM9260EK 2.1下载 介绍页: http://www.at91.com/linux4sam/bin/view/Linux4SAM/LegacyLinuxKernel 下载页: a ...
- sql小技巧 group by datetime类型字段,只取其中的日期部分
工作中经常会遇到,要在sql中查询报表,查询结果要求按照日期来罗列, 或按照天, 或按照月,年. 这个时候我们经常会苦恼,datetime是精确到毫秒的,如果单纯的group by datetime就 ...
- 王立平--Program Files (x86)
window7根据系统.program files(x86) 它是应用程序目录,在64下位系统.为了更好的相容性32位程序,在一些安装32位程序(请注意,有些节目自己是32位),将默认被安装progr ...