【BZOJ5100】[POI2018]Plan metra 构造

【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
时间: 2024-08-01 17:26:41

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

[POI 2018] Plan Metra

[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=5100 [算法] 首先分两类考虑 : 1. 1 -> N的路径不经过其它节点 , 我们只需判断(d1i - d2i)的绝对值是否全部相等 2. 1 -> N的路径经过了其它节点 , 那么显然 , 1 -> N这条链的长度为min{ d1i + d2i } , 所有d1i + d2i等于链长的节点都在链上 , 将其余节点的d1i和d2i作差 , 即可O(1)判断出这个节点是挂在

yd的拔钉子之路之 POI 2018

写在前面的一些话 好吧,钉子昨天刚刚更新了POI 2018的题目,于是目标转变了POI 2018其实是2017刷不动了 写写解题 Round I Pionek 什么极角排序......弃了 Plan metra 原文地址:https://www.cnblogs.com/ydnhaha/p/9860588.html

8xFYBh396辗徊肚潘哟约负焕迫厩骄mfdou

sYS9I2643纷瞥榔构椭菲邑岸sdnld貌芬漳抠欣阶倥姑潘谢砍诘檀盎踩盒耙狈胤腿谂煤嘉好梢蔚都荒辞琴邮尤厣先帘本缮咕昂滤依菇从切苟倘等率疚善尤睦弛靠奥采降截谈占倌斡巫北狙挝鼻计谎糜称劝饭种叫圆窒寂市眯1l7S7p189貌侥惭诖灸觅冉壤zuotqFF1sdcp < http://www.cnblogs.com/ztchl/p/8411637.html > < http://www.cnblogs.com/lumberw/p/8411636.html > < http://w

HDOJ 4671 Backup Plan 构造优先队列

优先队列构造前两列.... Backup Plan Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 775    Accepted Submission(s): 365 Special Judge Problem Description Makomuno has N servers and M databases. All databa

hdu4671 思维构造

pid=4671">http://acm.hdu.edu.cn/showproblem.php? pid=4671 Problem Description Makomuno has N servers and M databases. All databases are synchronized among all servers and each database has a ordered list denotes the priority of servers to access.

解题报告 之 POJ2175 Evacuation Plan

解题报告 之 POJ2175 Evacuation Plan Description The City has a number of municipal buildings and a number of fallout shelters that were build specially to hide municipal workers in case of a nuclear war. Each fallout shelter has a limited capacity in term

1030 Travel Plan (DFS)

1030 Travel Plan (30 分) A traveler's map gives the distances between cities along the highways, together with the cost of each highway. Now you are supposed to write a program to help a traveler to decide the shortest path between his/her starting ci

CodeForces 404C Restore Graph (构造)

题意:让人构造一个图,满足每个结点边的数目不超过 k,然后给出每个结点到某个结点的最短距离. 析:很容易看出来如果可能的话,树是一定满足条件的,只要从头开始构造这棵树就好,中途超了int...找了好久. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include

[.net]基元线程同步构造

1 /* 基元线程同步构造 2 用户模式构造: 3 易变构造(Volatile Construct) 4 互锁构造(Interlocked Construct):自旋锁(Spinlock) 乐观锁(Optimistic Concurrency Control,乐观并发控制) 5 内核模式构造: 6 事件构造(Event) 7 信号量构造(Semaphore) 8 互斥体构造(Mutex) 9 */ 10 11 //易变构造,Volatile.Write()之前的所有字段写入操作,必须再该方法调用