洛谷 #1351. 聯合權值

題意

一棵樹上距離爲2的兩個節點的權值相乘,問max和sum

題解

70分:枚舉每個節點,它的兩個兒子必定距離爲2,相加、取max即可(會T)

100分:注意到,一個節點的兒子中,互相都要乘

根據乘法分配律,我先預處理它兒子的權值和,每個節點x對聯合權值的貢獻爲key[x] * (sum - key[x])

這樣可以把O(\(\ n3\))的時間複雜度降至O(\( n2\))

調試記錄

(70分代碼)最後sum要*2

而且還要%

70分代碼

#include <cstdio>
#include <algorithm>
#define maxn 200005
#define mo 10007
#define INF 0x3f3f3f3f

using namespace std;

struct node{
	int to, next;
}e[maxn << 1];

int n, tot, head[maxn], key[maxn];

void AddEdge(int u, int v){
	e[++tot] = (node){v, head[u]}; head[u] = tot;
	e[++tot] = (node){u, head[v]}; head[v] = tot;
}

int main(){
	scanf("%d", &n);
	
	for (int x, y, i = 1; i < n; i++){
		scanf("%d%d", &x, &y); AddEdge(x, y);
	}
	
	for (int i = 1; i <= n; i++) scanf("%d", &key[i]);
	
	long long sum = 0; int maxkey = -INF;
	for (int i = 1; i <= n; i++){
		for (int u = head[i]; u; u = e[u].next){
			for (int v = e[u].next; v; v = e[v].next){
				sum = (sum + key[e[u].to] * key[e[v].to]) % mo;
				maxkey = max(maxkey, key[e[u].to] * key[e[v].to]);
			}
		}
	}
	printf("%d %lld\n", maxkey, sum * 2 % mo);
	
	return 0;
}

100分代碼

#include <cstdio>
#include <algorithm>
#define maxn 200005
#define mo 10007
#define INF 0x3f3f3f3f

using namespace std;

struct node{
	int to, next;
}e[maxn << 1];

int n, tot, head[maxn], key[maxn];

void AddEdge(int u, int v){
	e[++tot] = (node){v, head[u]}; head[u] = tot;
	e[++tot] = (node){u, head[v]}; head[v] = tot;
}

int main(){
	scanf("%d", &n);
	
	for (int x, y, i = 1; i < n; i++){
		scanf("%d%d", &x, &y); AddEdge(x, y);
	}
	
	for (int i = 1; i <= n; i++) scanf("%d", &key[i]);
	
	/*long long sum = 0; int maxkey = -INF; Getting sum/max for 70 points
	for (int i = 1; i <= n; i++){
		for (int u = head[i]; u; u = e[u].next){
			for (int v = e[u].next; v; v = e[v].next){
				sum = (sum + key[e[u].to] * key[e[v].to]) % mo;
				maxkey = max(maxkey, key[e[u].to] * key[e[v].to]);
			}
		}
	}*/
	
	long long certain_sum, sum = 0; int maxkey = -INF;
	for (int i = 1; i <= n; i++){
		certain_sum = 0;
		int tmp1 = 0, tmp2 = 0;
		for (int u = head[i]; u; u = e[u].next){
			certain_sum += key[e[u].to];
			if (key[e[u].to] > tmp1) tmp2 = tmp1, tmp1 = key[e[u].to]; 
			else if (key[e[u].to] > tmp2) tmp2 = key[e[u].to];
		}
		maxkey = max(maxkey, tmp1 * tmp2);
		for (int u = head[i]; u; u = e[u].next){
			sum = (sum + key[e[u].to] * (certain_sum - key[e[u].to])) % mo;
		}
	}
	printf("%d %lld\n", maxkey, sum % mo);
	
	return 0;
}
//https://www.luogu.org/problemnew/show/P1351
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章