2022“杭电杯”中国大学生算法设计超级联赛(6)补题

1006  Maex

题意

给你一个有根树,由编号从1到n的n个顶点组成,根是顶点1。 顶点i有一个自然数权重ai,没有两个不同的顶点具有相同的权重。bu​=MEX { x ∣ ∃v∈subtree(u),x=av​}。不幸的是,ai都不是给定的。请找出最大可能的∑(i=1)b。集合的MEX是不属于该集合的最小非负整数。

思路

本题采用树形dp。本题要求b数组的和的最大值,而b数组是以该结点为根的子树的权值中没有出现过的最小非负整数,要使它最大就应该使子树中尽可能出现更小的数,越小的数越应该出现在树叶部分,以使得层数越高的结点有越大的值,此时每个结点的b值等于该子树的结点个数。采用两个dfs,第一个dfs用来计算以各结点为根的子树的结点数目,第二个dfs用来计算最大权值之和。

代码

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <deque>
#include <stdio.h>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define int long long
using namespace std;
int n;
const int N=500005;
int head[N],to[2*N],nxt[2*N];
int jd[N],du[N],qz[N];
int inf,cnt;
void add(int u,int v)
{
	to[cnt]=v;
	nxt[cnt]=head[u];
	head[u]=cnt++;
}
void dfs1(int u,int fa)//以该点为根的子树中包含的结点数目
{
	jd[u]=1;
	for(int i=head[u];i!=-1;i=nxt[i])
	{
		int j=to[i];
		if(j==fa)
			continue;
		dfs1(j,u);
		
		jd[u]+=jd[j];
	}
}
void dfs2(int u,int fa)//一条链上所能获得的最大权值之和
{
	if(fa==-1)
		qz[u]=jd[u];
	else
		qz[u]=jd[u]+qz[fa];
	if(du[u]==1)
	{
		inf=max(inf,qz[u]);
	}
	for(int i=head[u];i!=-1;i=nxt[i])
	{
		int j=to[i];
		if(j==fa)
			continue;
		dfs2(j,u);
	}
}
signed main()
{
	IOS;
	
	int t;
	cin>>t;
	int u,v;
	int i,j;
	while(t--)
	{
		cin>>n;
		if(n==1)
		{
			cout<<"1\n";
			continue;
		}
		
		for(i=0;i<=n;i++)
		{
			head[i]=-1;
			du[i]=0;
			qz[i]=0;
			jd[i]=0;
		}
		inf=-0x3f3f3f3f;
		cnt=0;
		
		for(i=1;i<n;i++)
		{
			cin>>u>>v;
			add(u,v);
			add(v,u);
			du[u]++;
			du[v]++;
		}
		
		dfs1(1,-1);
		dfs2(1,-1);
		cout<<inf<<endl;
	}
	
	
	
	
	
	return 0;
}

1009  Map

题意

Sakuyalove有一个大的世界地图M和一个小的世界地图m,两个都是长方形的。小图m由大图M压缩而来,如果M的长度是a,M的宽度是b,那么m的长度是ka,m的宽度是kb,其中0<k<1。现在Sakuyalove把小地图m放到大地图M上,这样小地图就完全在大地图之内(包括边界)。她惊讶地发现,无论她如何放置小地图,总是恰好存在一个点P代表小地图和大地图中的相同位置。求P的位置坐标。

思路

本题采用巴拿赫不动点定理来计算定点。

通过求解二元一次方程组求得那两个变量,然后再将其带入第一个式子直接求得x和y。

 

 通过这个式子可以直接求得那两个变量的值。

代码

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <deque>
#include <stdio.h>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define int double
using namespace std;
struct node
{
	int x,y;
};
node A,B,C,D,a,b,c,d;
signed main()
{
	IOS;
	
	int t;
	cin>>t;
	int i,j;
	int ABx,ABy,abx,aby,ADx,ADy,adx,ady,Aax,Aay;
	int aa,bb,cc,dd,ee,ff;
	int x,y;
	int xb,yb;
	while(t--)
	{
		cin>>A.x>>A.y>>B.x>>B.y>>C.x>>C.y>>D.x>>D.y
			>>a.x>>a.y>>b.x>>b.y>>c.x>>c.y>>d.x>>d.y; 
		
		
		aa=(B.x-A.x)-(b.x-a.x);
		bb=(D.x-A.x)-(d.x-a.x);
		cc=a.x-A.x;
		dd=(B.y-A.y)-(b.y-a.y);
		ee=(D.y-A.y)-(d.y-a.y);
		ff=a.y-A.y;
		
		y=(ff*1.0-dd/aa*cc)/(ee-dd/aa*bb);
		x=(cc-bb*y)/aa;
		
		int xb=A.x+x*(B.x-A.x)+y*(D.x-A.x);
		int yb=A.y+x*(B.y-A.y)+y*(D.y-A.y);
		
		cout<<fixed<<setprecision(6)<<xb<<" "<<yb<<endl;
	}
	
	
	
	
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值