【BZOJ5100】[POI2018]Plan metra

Description

有一棵n个点的无根树,每条边有一个正整数权值,表示长度,定义两点距离为在树上的最短路径的长度。
已知2到n-1每个点在树上与1和n的距离,请根据这些信息还原出这棵树。

Input

第一行包含一个正整数n(2<=n<=500000),表示点数。
第二行包含n-2个正整数d(1,2),d(1,3),...,d(1,n-1),分别表示每个点到1的距离。
第三行包含n-2个正整数d(n,2),d(n,3),...,d(n,n-1),分别表示每个点到n的距离。
输入数据保证1<=d<=1000000。

Output

若无解,输出NIE。
否则第一行输出TAK,接下来n-1行每行三个正整数u,v,c(1<=u,v<=n,1<=c<=1000000)
表示存在一条长度为c的连接u和v两点的树边。
若有多组解,输出任意一组。

Sample Input

7
6 6 2 2 1
5 3 5 1 4

Sample Output

TAK
1 5 2
5 7 1
5 2 4
7 3 3
1 4 2
1 6 1

题解:如果我们已经确定了点1到点n的距离,那么我们就可以将1到n这条路拿出来,然后其他点都想挂链一样挂到这条路径上即可。即:

如果1到n的长度是m,我们将所有d1-dn相同的点放到一起,那么对于每组d1-dn相同的点,要么|d1-dn|=m,要么d1+dn的最小值=m。所以用数组记录一下即可。

输出方案的时候将所有d1+dn=m的点排个序即可。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int N=500010;
const int M=1000010;
int n,m,tot,cnt;
int d1[N],d2[N],s1[M<<1],s2[M<<1],p[M],mn[M<<1],pa[N],pb[N],pc[N];
inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd()
{
int ret=0,f=1; char gc=nc();
while(!isdigit(gc)) {if(gc=='-') f=-f; gc=nc();}
while(isdigit(gc)) ret=ret*10+(gc^'0'),gc=nc();
return ret*f;
}
inline int abs(int x) {return x>0?x:-x;}
inline bool check(int x)
{
if(((x>=M||x<=-M)?0:(s1[M+x]+s1[M-x]))+s2[x]==n-2)
{
m=x;
return 1;
}
return 0;
}
inline void add(int a,int b,int c)
{
pa[++cnt]=a,pb[cnt]=b,pc[cnt]=c;
}
int main()
{
n=rd();
if(n==2)
{
printf("TAK\n1 2 1");
return 0;
}
register int i,last;
for(i=2;i<n;i++) d1[i]=rd();
for(i=2;i<n;i++)
{
d2[i]=rd();
int &t=mn[d2[i]-d1[i]+M];
if(!t||d1[t]+d2[t]>d1[i]+d2[i]) t=i;
s1[d2[i]-d1[i]+M]++;
}
for(i=2;i<n;i++) if(i==mn[d2[i]-d1[i]+M]) s2[d1[i]+d2[i]]+=s1[d2[i]-d1[i]+M];
for(i=2;i<n;i++) if(check(abs(d2[i]-d1[i]))||check(d1[i]+d2[i])) break;
if(!m)
{
puts("NIE");
return 0;
}
for(i=2;i<n;i++)
{
if(d2[i]-d1[i]==m) add(i,1,d1[i]);
else if(d1[i]-d2[i]==m) add(i,n,d2[i]);
else if(i==mn[d2[i]-d1[i]+M]) p[d1[i]]=i;
else
{
int t=mn[d2[i]-d1[i]+M];
add(i,t,(d1[i]+d2[i]-d1[t]-d2[t])>>1);
}
}
p[m]=n,d1[n]=m;
for(last=i=1;i<=m;i++) if(p[i]) add(last,p[i],d1[p[i]]-d1[last]),last=p[i];
for(i=1;i<n;i++) if(pc[i]<=0)
{
puts("NIE");
return 0;
}
puts("TAK");
for(i=1;i<n;i++) printf("%d %d %d\n",pa[i],pb[i],pc[i]);
return 0;
}//6 2 5 4 8 4 1 6 4

【BZOJ5100】[POI2018]Plan metra 构造的更多相关文章

  1. bzoj5100 [POI2018]Plan metra 构造

    5100: [POI2018]Plan metra Time Limit: 40 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 189  Sol ...

  2. bzoj千题计划249:bzoj5100: [POI2018]Plan metra

    http://www.lydsy.com/JudgeOnline/problem.php?id=5100 1.找到d1[i]+dn[i] 最小的点,作为1到n链上的点 2.令链长为D,若abs(d1[ ...

  3. BZOJ5100 : [POI2018]Plan metra

    若$1$到$n$之间没有其它点,则$1$到$n$的距离为任意一点到它们距离的差值,按照距离关系判断每个点是挂在$1$上还是挂在$n$上即可. 否则$1$到$n$的距离只可能为任意一点到它们距离和的最小 ...

  4. [POI2018]Plan metra

    题目大意: 一棵$n(n\le5\times10^5)$个结点的树,每条边的边权均为正整数,告诉你$2\sim n-1$号结点到$1$号点和$n$号点的距离$d1[i]$和$d2[i]$.求是否存在这 ...

  5. 题解【洛谷P5959】[POI2018]Plan metra

    题面 一道比较神仙的构造题. 首先确定 \(1\) 到 \(n\) 的路径长度,不妨设其长为 \(m\) . 通过观察发现,\(m\) 就是 \(\min_{1<i<n}\{dist_{1 ...

  6. [POI 2018] Plan Metra

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=5100 [算法] 首先分两类考虑 : 1. 1 -> N的路径不经过其它节点 , ...

  7. POI2018

    [BZOJ5099][POI2018]Pionek(极角排序+two pointers) 几个不会严谨证明的结论: 1.将所有向量按极角排序,则答案集合一定是连续的一段. 当答案方向确定时,则一个向量 ...

  8. BZOJ5100 POI2018Plan metra(构造)

    容易发现要么1和n直接相连,要么两点距离即为所有dx,1+dx,n的最小值.若为前者,需要满足所有|d1-dn|都相等,挂两棵菊花即可.若为后者,将所有满足dx,1+dx,n=d1,n的挂成一条链,其 ...

  9. HDU 4671 Backup Plan (2013多校7 1006题 构造)

    Backup Plan Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total ...

随机推荐

  1. html2canvas如何在元素隐藏的情况下生成截图

    html2canvas官网地址:http://html2canvas.hertzen.com/ github地址:https://github.com/niklasvh/html2canvas/ 从官 ...

  2. Linux之zip压缩

    1.压缩 对于test目录,使用 zip -rq test.zip test r表示递归压缩,q表示不显示过程 2.解压缩 unzip -q test.zip

  3. yasm开源汇编器分析

    https://www.google.com.hk/search?q=yasm&oq=yasm&aqs=chrome..69i57&sourceid=chrome&es ...

  4. 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果(转)

    转载:http://blog.csdn.net/xiaanming/article/details/10163203 了解二维码这个东西还是从微信 中,当时微信推出二维码扫描功能,自己感觉挺新颖的,从 ...

  5. 深入了解Android蓝牙Bluetooth ——《总结篇》

    在我的上两篇博文中解说了有关android蓝牙的认识以及API的相关的介绍,蓝牙BLE的搜索,连接以及读取. 没有了解的童鞋们请參考: 深入了解Android蓝牙Bluetooth--<基础篇& ...

  6. KO 数据库分类系统介绍

    KEGG Orthology数据库不仅对基因的功能进行了扩充和整理,还对功能进行了细致的分类: 针对基因的功能,共有3级分类,第一级有6个大类: 打开下面这个链接 http://www.genome. ...

  7. Java回调方法的设计思路

    package com.test; /** * 回调方法的设计技巧,例如hibernate的getHibernateTemplate().execute(Handler h)方法 */ public ...

  8. Kubernetes1.1源码分析(二)

    3.controller-manager模块 在controller manager模块中有几个重要的结构体.当中包含EndpointController.ReplicationManager.GCC ...

  9. Android学习笔记——Menu(二)

    知识点: 这次将继续上一篇文章没有讲完的Menu的学习,上下文菜单(Context menu)和弹出菜单(Popup menu). 上下文菜单 上下文菜单提供对UI界面上的特定项或上下文框架的操作,就 ...

  10. 第五章 面向方面编程___AOP入门

    上一篇讲了 AOP 和 OOP 的区别,这一次我们开始入门 AOP .实现面向方面编程的技术,主要分为两大类: 一是 采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行: ...