【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. 微信小程序——获取绑定事件元素的ID

    小程序list数据带值跳转,一般直接通过设置item的id来标识或者通过设置键值data-xxxx的方式标识.如下图所示: 解析出来的结果如下图: 我们看到它在元素上绑定了一个checkSchoolL ...

  2. 中国餐馆过程(Chinese restaurant process)

    也就是说假设空桌子有a0个人,然后顾客选择桌子的概率和桌子上人数成正比. 性质: 改变用户的排列方式,桌子的排列方式,概率不变换.

  3. Android Activity 传递数据

    activity中数据的传递方式有2中,一种是使用putExtra()传递,另外一种是传递Bundle对象,使用putExtras()方法. 方法一 发送数据 putExtra()传送的是键值对,第一 ...

  4. e682. 获得打印页的尺寸

    Note that (0, 0) of the Graphics object is at the top-left of the actual page, which is outside the ...

  5. e555. 在Applet中播放音频

    // See also e551 精简的Applet public void init() { // Load audio clip AudioClip ac = getAudioClip(getDo ...

  6. 有一个TIME的类要求输出分和秒的值

    #include <iostream> /* run this program using the console pauser or add your own getch, system ...

  7. 用cxf生成webservice的java客户端代码

    百度来的: 最近,由于要用到某公司提供的webservice实现的api接口,想到了用cxf的wsdl2java工具来生成客户端程序.(自己写是比较麻烦且费时,so偷懒一下..) 使用步骤如下: 一. ...

  8. More is better-多多益善

    思路:在图中所有的连通分量中找出包含顶点最多的个数.继续使用并查集解决! #include <iostream> using namespace std; ; int tree[MAX]; ...

  9. [mysql] 先按某字段分组再取每组中前N条记录

    From: http://blog.chinaunix.net/uid-26729093-id-4294287.html 请参考:http://bbs.csdn.net/topics/33002126 ...

  10. Digest Authentication 摘要认证

    “摘要”式认证( Digest authentication)是一个简单的认证机制,最初是为HTTP协议开发的,因而也常叫做HTTP摘要,在RFC2671中描述.其身份验证机制很简单,它采用杂凑式(h ...