联合权值——呆滞大佬der最骚操作?

2023-10-19 11:40

本文主要是介绍联合权值——呆滞大佬der最骚操作?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目描述:

无向连通图G 有n 个点,n - 1 条边。点从1 到n 依次编号,编号为 i 的点的权值为W i ,每条边的长度均为1 。图上两点( u , v ) 的距离定义为u 点到v 点的最短距离。对于图G 上的点对( u, v) ,若它们的距离为2 ,则它们之间会产生Wu×Wv 的联合权值。

请问图G 上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少?

输入格式:

第一行包含1 个整数n 。

接下来n - 1 行,每行包含 2 个用空格隔开的正整数u 、v ,表示编号为 u 和编号为v 的点之间有边相连。

最后1 行,包含 n 个正整数,每两个正整数之间用一个空格隔开,其中第 i 个整数表示图G 上编号为i 的点的权值为W i 。

输出格式:

输出共1 行,包含2 个整数,之间用一个空格隔开,依次为图G 上联合权值的最大值

和所有联合权值之和。由于所有联合权值之和可能很大,输出它时要对10007 取余。

样例输入:

5  
1 2  
2 3
3 4  
4 5  
1 5 2 3 10 

样例输出:

20 74

提示:

【样例说明】

1498614983226819123.png

本例输入的图如上所示,距离为2 的有序点对有( 1,3) 、( 2,4) 、( 3,1) 、( 3,5) 、( 4,2) 、( 5,3) 。

其联合权值分别为2 、15、2 、20、15、20。其中最大的是20,总和为74。

【数据说明】

对于30% 的数据,1 < n≤ 100 ;

对于60% 的数据,1 < n≤ 2000;

对于100%的数据,1 < n≤ 200 , 000 ,0 < wi≤ 10, 000 。

时间限制:1000ms
空间限制:256MByte

这个题目暴力枚举很明显不是正解,但是显然我们需要将各种点之间是否相连这个状态给保存下来,但是由题目可知,n<=200000,所以要是开二维数组开满的话起码得要20万*20万的数组,这个肯定是开不下的。所以这个时候又是STL上场的时候了,我们可以用vector来减少无用的空间。同时这个题目中所求的联合权值的总和可以用加法结合律来优化(虽然听起来很智障,但是用还是很好用的)。对于一个节点来说,可以被看成是其相连两个节点的中间点,假设有点s连着a,b,c,d四个点,所以对于s来说其联合权值的总和为ab+ac+ad+bc+bd+cd,所以就是加法结合律了,等等,你可能会发现一个东西,这怎么用加法结合律。其实,以上这个式子是错的,因为题目中有一句话讲到一下几个字,有!序!点!对!所以说,ac与ca都是要算一遍的,所以其实是,ab+ac+ad+ba+bc+bd+ca+cb+cd+da+db+dc,然后就是a*(b+c+d)+b*(a+c+d)+c*(a+b+d)+d*(a+b+c),(这个是不是乘法结合律?)所以我们可以看成a*(sum-a)+b*(sum-b)+c*(sum-c)+d*(sum-d),所以将每个节点边上节点权值之和求出放在结构体中,这个问题就被大大地简化了。

#include<bits/stdc++.h>
using namespace std;
vector v[200001];
long long s[200001],w[200001],n,maxn,sum;
int main(){cin>>n;for (int i=1,a,b; i<n; i++){cin>>a>>b;v[a].push_back(b);//将与a相连的点存在v[a]中v[b].push_back(a);//将与b相连的点存在v[b]中}for (int i=1; i<=n; i++)cin>>w[i];//w记录点的权值for (int i=1; i<=n; i++){long long maxn1,maxn2;maxn1=0;maxn2=0;for (int l=0; l<v[i].size(); l++){s[i]+=w[v[i][l]];//s[i]存与i节点相连的节点权值之和if (s[i]>10007) s[i]-=10007;//玄学,减比取模快if (w[v[i][l]]>maxn1){maxn2=maxn1;maxn1=w[v[i][l]];}//maxn1与maxn2分别为与i节点相连节点中第一和第二大的权值else if (w[v[i][l]]==maxn1 || w[v[i][l]]>maxn2)maxn2=w[v[i][l]];}//随时准备更新manx2if (maxn1*maxn2>maxn)maxn=maxn1*maxn2;//maxn即为最大权值}for (int i=1; i<=n; i++){for (int l=0; l<v[i].size(); l++){sum+=(s[i]-w[v[i][l]])*w[v[i][l]];//迷之加法结合律(乘法结合律)sum%=10007;	}}cout<<maxn<<" "<<sum%10007;return 0;
}

你以为这篇博客到这里就完了?大错特错,标题告诉我们,接下来才是正题,那就是呆滞大佬der最骚操作。呆滞大佬当初写这个题目的时候,就想到了他之前那写过的天天爱跑步,于是他就写了一个弱化的天天爱跑步(虽然感觉这两个题目没有任何关系)。呆滞大佬的想法就是,用两个结构体,分别是点和边,其中的边是有向边,题目中为无向边,只要看成两条无向边即可。我们可以先贴代码,然后再讲些别的东西。

#include<bits/stdc++.h>
using namespace std;
const int mos=200005;
struct point{long long ti,value,first,second,sum;
}b[mos<<1];
struct edge{int sta,ed;//就是start和end
}a[mos<<1];
bool mmp(edge a,edge b){return a.sta<b.sta;
}
long long num1=0,num2=0,x,n,ss;
int main(){cin>>n;for (int i=1; i<n; i++){cin>>a[(i<<1)-1].sta>>a[(i<<1)-1].ed;a[i<<1].sta=a[(i<<1)-1].ed;a[i<<1].ed=a[(i<<1)-1].sta;b[a[i<<1].sta].ti++;b[a[i<<1].ed].ti++;}sort(a+1,a+(n<<1)-1,mmp);//将边按照起点从小到大排序for (int i=1; i<=n; i++)b[i].ti+=b[i-1].ti;//求ti的前缀和。for (int i=1; i<=n; i++)cin>>b[i].value;for (int i=1; i<=n; i++){for (int l=b[i-1].ti+1; l<=b[i].ti; l++){b[i].sum+=b[a[l].ed].value;if (b[a[l].ed].value>b[i].first){b[i].second=b[i].first;b[i].first=b[a[l].ed].value;}else if (b[a[l].ed].value>b[i].second) b[i].second=b[a[l].ed].value;}b[i].sum%=10007;}for (int i=1; i<=n; i++){for (int l=b[i-1].ti+1; l<=b[i].ti; l++){num2+=b[i].value*(b[a[l].ed].sum-b[i].value);num2%=10007;if (ss<b[a[l].ed].first*b[a[l].ed].second)ss=b[a[l].ed].first*b[a[l].ed].second;if (ss>num1) num1=ss;}}cout<<num1<<" "<<num2;return 0;
}

其中最迷离的应该是在point结构体中的ti变量了,ti所代表的意思即为b节点在边中为起点的次数。其中最骚的就是这个ti的前缀和了!看完这个代码你就会发现呆滞大佬用ti的前缀和解决了开无用数组所造成的浪费,其中b[i].ti-b[i-1].ti-1就是在上一个程序中的vector v.size(),这样是坠骚滴。b[i].ti和a[b[i].ti]的关系就是不言而喻的,慢慢体会就会感觉……异常地骚。震惊!明天居然还要考试!

made by cain-

转载于:https://www.cnblogs.com/cain-/p/7306003.html

这篇关于联合权值——呆滞大佬der最骚操作?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/239540

相关文章

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密

加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version></dependency> 编写一个AES加密

动手学深度学习【数据操作+数据预处理】

import osos.makedirs(os.path.join('.', 'data'), exist_ok=True)data_file = os.path.join('.', 'data', 'house_tiny.csv')with open(data_file, 'w') as f:f.write('NumRooms,Alley,Price\n') # 列名f.write('NA

线程的四种操作

所属专栏:Java学习        1. 线程的开启 start和run的区别: run:描述了线程要执行的任务,也可以称为线程的入口 start:调用系统函数,真正的在系统内核中创建线程(创建PCB,加入到链表中),此处的start会根据不同的系统,分别调用不同的api,创建好之后的线程,再单独去执行run(所以说,start的本质是调用系统api,系统的api

Java IO 操作——个人理解

之前一直Java的IO操作一知半解。今天看到一个便文章觉得很有道理( 原文章),记录一下。 首先,理解Java的IO操作到底操作的什么内容,过程又是怎么样子。          数据来源的操作: 来源有文件,网络数据。使用File类和Sockets等。这里操作的是数据本身,1,0结构。    File file = new File("path");   字

MySQL——表操作

目录 一、创建表 二、查看表 2.1 查看表中某成员的数据 2.2 查看整个表中的表成员 2.3 查看创建表时的句柄 三、修改表 alter 3.1 重命名 rename 3.2 新增一列 add 3.3 更改列属性 modify 3.4 更改列名称 change 3.5 删除某列 上一篇博客介绍了库的操作,接下来来看一下表的相关操作。 一、创建表 create

封装MySQL操作时Where条件语句的组织

在对数据库进行封装的过程中,条件语句应该是相对难以处理的,毕竟条件语句太过于多样性。 条件语句大致分为以下几种: 1、单一条件,比如:where id = 1; 2、多个条件,相互间关系统一。比如:where id > 10 and age > 20 and score < 60; 3、多个条件,相互间关系不统一。比如:where (id > 10 OR age > 20) AND sco

PHP7扩展开发之流操作

前言 啥是流操作?简单来讲就是对一些文件,网络的IO操作。PHP已经把这些IO操作,封装成流操作。这节,我们将使用PHP扩展实现一个目录遍历的功能。PHP示例代码如下: <?phpfunction list_dir($dir) {if (is_dir($dir) === false) {return;} $dh = opendir($dir);if ($dh == false) {ret

浙大数据结构:树的定义与操作

四种遍历 #include<iostream>#include<queue>using namespace std;typedef struct treenode *BinTree;typedef BinTree position;typedef int ElementType;struct treenode{ElementType data;BinTree left;BinTre

浙大数据结构:04-树7 二叉搜索树的操作集

这道题答案都在PPT上,所以先学会再写的话并不难。 1、BinTree Insert( BinTree BST, ElementType X ) 递归实现,小就进左子树,大就进右子树。 为空就新建结点插入。 BinTree Insert( BinTree BST, ElementType X ){if(!BST){BST=(BinTree)malloc(sizeof(struct TNo

hibernate修改数据库已有的对象【简化操作】

陈科肇 直接上代码: /*** 更新新的数据并并未修改旧的数据* @param oldEntity 数据库存在的实体* @param newEntity 更改后的实体* @throws IllegalAccessException * @throws IllegalArgumentException */public void updateNew(T oldEntity,T newEntity