列表

详情


NC15192. 直径

描述

给你N个点的树,每条边都有权重。
定义树上两个点的距离为此两点所形成的路径的权重和。
N个点能形成N(N-1)/2组点对,把这些点对的距离由大到小排序后,请输出前K大的距离数值。(若多组相异点对距离相同,该距离就要算不止一次)

输入描述

数据共有N行。
第一行包含两个正整数N,K,分别代表树的点数以及要输出前几大的点对距离。
接下来的N-1行每行个包含三个整数x,y,v代表此树中,点x和点y之间有一条权重为v的边。

输出描述

请输出K行,每行各包含一个正整数,第i行的数字代表第i大的点对距离。

示例1

输入:

4 6
0 1 1
0 2 2
0 3 4

输出:

6
5
4
3
2
1

示例2

输入:

7 20
0 1 3
0 2 2
1 3 11
1 4 5
2 5 23
2 6 7

输出:

39
33
30
28
25
23
23
17
16
16
14
12
11
10
9
8
7
5
5
3

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 399ms, 内存消耗: 186088K, 提交时间: 2018-10-20 23:29:18

#include<bits/stdc++.h>
using namespace std;
#define N 200010
#define mst(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=a;i<=b;i++)


int head[N],edge_cnt;
struct edge {
	int to,w,nxt;
} E[N<<1];


void add(int x,int y,int z) {
	E[edge_cnt]= {y,z,head[x]};
	head[x] = edge_cnt++;
}
int n,K;
vector<long long>A[N],ans,tmp;
priority_queue<long long,vector<long long>,greater<long long> >q;

void dfs(int x,int f) {
	A[x].push_back(0);
	int i,j,k;
	for (i=head[x]; ~i; i=E[i].nxt) {
		int to=E[i].to,val=E[i].w;
		if (to==f) continue;
		dfs(to,x);
		int R1=(int)A[x].size(),R2=(int)A[to].size();
		for (k=0; k<R2; k++) A[to][k]+=val;
		for (j=0; j<R1; j++)
			for (k=0; k<R2; k++) {
				long long t=A[x][j]+A[to][k];
				if ((int)q.size()<K) {
					q.push(t);
				} else if (t>q.top()) {
					q.pop();
					q.push(t);
				} else {
					break;
				}
			}
		tmp.clear();
		j=0,k=0;
		int h=0;
		while (h<K && j<R1 && k<R2) {
			h++;
			if (A[x][j]>=A[to][k]) tmp.push_back(A[x][j++]);
			else tmp.push_back(A[to][k++]);
		}
		while (h<K && j<R1) h++,tmp.push_back(A[x][j++]);
		while (h<K && k<R2) h++,tmp.push_back(A[to][k++]);
		A[x]=tmp;
	}
}
//**************************************
int main() {
	mst(head,-1);
	scanf("%d %d",&n,&K);
	rep(i,2,n) {
		int x,y,z;
		scanf("%d %d %d",&x,&y,&z);
		add(x+1,y+1,z);
		add(y+1,x+1,z);
	}
	dfs(1,1);
	while(!q.empty()) {
		ans.push_back(q.top());
		q.pop();
	}
	while((int)ans.size() > 0) {
		printf("%lld\n",*(--ans.end())),ans.pop_back();
	}
}
//**************************************

C++11(clang++ 3.9) 解法, 执行用时: 712ms, 内存消耗: 189032K, 提交时间: 2018-03-03 21:45:16

#include<bits/stdc++.h>
#define SZ(X) (int)((X).size())
typedef long long LL;
using namespace std;
const int MAX_N = 200000;
const int MAX_K = 58311;
int N,K;
priority_queue<LL,vector<LL>,greater<LL> >ma_dises;
vector<pair<int,int> >e[MAX_N];
vector<LL>ma[MAX_N];
void read() {
	scanf("%d%d",&N,&K);
	for(int i=1; i<N; i++) {
		int x,y,v;
		scanf("%d%d%d",&x,&y,&v);
		e[x].push_back({y,v});
		e[y].push_back({x,v});
	}
}
void add(LL v) {
	if(SZ(ma_dises)<K)ma_dises.push(v);
	else if(v>ma_dises.top()) {
		ma_dises.push(v);
		ma_dises.pop();
	}
}
LL tmp[MAX_K*2];
void dfs(int x,int lt) {
	ma[x]=vector<LL>(1);
	for(int i=0; i<SZ(e[x]); i++) {
		int y,v;
		y=e[x][i].first;
        v=e[x][i].second;
		if(y==lt)continue;
		dfs(y,x);
		for(int j=0; j<SZ(ma[y]); j++) {
			ma[y][j]+=v;
			for(int k=0; k<SZ(ma[x]); k++) {
				add(ma[x][k]+ma[y][j]);
			}
		}
		merge(ma[x].begin(),ma[x].end(),ma[y].begin(),ma[y].end(),tmp,greater<LL>());
		ma[x]=vector<LL>(tmp,tmp+min(K,SZ(ma[x])+SZ(ma[y])));
	}
}
void solve() {
	dfs(0,0);
	vector<LL> res;
	while(SZ(ma_dises)) {
		res.push_back(ma_dises.top());
		ma_dises.pop();
	}
	for(int i=(int)res.size()-1; i>=0; i--) {
		printf("%lld\n",res[i]);
	}
}
int main() {
	read();
	solve();
	return 0;
}

上一题