CSP-S2023T1

引入

山川点点路千重,小熊寻景历四踪
转车限制行次间,分数求和愿最丰

前言

这道题很招笑,从绿题变成蓝题了,主要难度就在于细节过多,又有了一次t1难于t2的例子

题目大意

  • 给一张图,从里面选取4个点与根节点1构成一个环,求所取环点权相加的最大值(不包括根节点1)
  • 注意任意两个点之间的距离不能大于k+1(k已给出)
  • 点的数量不超过2500个

题目分析

首先不难看出,我们应该先以k的限制在所给出的图的基础上构建一个新图,把任意一个对于点v距离小于(k+1)的点u与点v建立一条边,以新建边构成一个新图
接着朴素的算法就是直接进行 O(n^4) 的枚举,枚举路径上的四个点并且1号结点与4号结点都与1联通,预计得分能到达 70
根据朴素思想可以看出,我们可以只枚举四个点中的第2与4号结点
对于一个2号与4号结点 v1 ,v2,找出可以连接 v1 或 v2 且连接1的所有最大点权点 u1 或 u2 ,四点就构成了一条以v1 v2为2号四号结点的最大环
要注意,由于对于一个u有可能与另一v相等或两u相等,所以要对一个点v准备三个值排除相同情况

代码实现

构图

构图很简单,具体有以下几步

  • 链式前向星存图
void add(long long x,long long y){
	e[++cnt].v=y,e[cnt].nx=he[x],he[x]=cnt;//没什么好讲的 
} 
  • 以及
for(long long i=1;i<=m;i++){
		long long x,y;
		cin>>x>>y;
		s[x][y]=1;
		add(x,y);
		add(y,x);
	}
  • 通过bfs构建新图图1
  • 如图,可以看到样例中1与2连接,2与3连接,3与4连接且k=1
  • 我们就可以先把2构建边并入队,接着找到3,由于此时2到给出发点1距离 \(s=1<=k\) 所以3与1构建新边并入队
  • 由于3的距离 \(s=2>k\) 故4不能入队同时无法构建新边
for(long long k1=1;k1<=n;k1++){
		queue<long long> q;
		memset(vis,0,sizeof(vis));
		q.push(k1);
		vis[k1]=1;
		while(!q.empty()){
			long long x=q.front();
			q.pop();
			for(long long i=he[x];i;i=e[i].nx){
				long long y=e[i].v;
				if(k1==y)
				continue;
				if(vis[y]==0&&v[k1][x]<=k){//出发点是否能到达 
				    s[k1][y]=1;//新边 
					vis[y]=1;
					q.push(y);
					v[k1][y]=v[k1][x]+1;//距离存储 

				}
			}
		}
	}
  • 此算法可以在 \(O(n^2)\)下完成

枚举每结点的u

  • 枚举每个结点u所连接的v且v连接1,接着判断v可以存入最大值、次大值、次次大值中哪一位
for(long long i=2;i<=n;i++){
		for(long long j=2;j<=n;j++){
			if(j==i)continue;
			if((s[i][j]==1||s[j][i]==1)&&(s[1][j]==1&&s[j][1]==1)){
				p(i,j);
			}
		}
	}
  • 枚举
void p(long long x,long long y){
	if(a[y]>a[w[x][1]]){
		w[x][2]=w[x][1];
		w[x][3]=w[x][2];
		w[x][1]=y;
	}
	else if(a[y]>a[w[x][2]]){
		w[x][3]=w[x][2];
		w[x][2]=y;
	}
	else{
		if(a[y]>a[w[x][3]])
		w[x][3]=y;
	}
}
  • 判断

枚举寻找最大环

  • 代码实现如之前的分析,枚举2号4号结点取最大环比较最大值即可
for(long long i=2;i<=n;i++){
		for(long long j=2;j<=n;j++){
			if(j==i)continue;
			if(s[i][j]==0)//两点要连接 
			continue;
			for(long long uu=1;uu<=3;uu++){
				for(long long vv=1;vv<=3;vv++){
					if(w[i][uu]==0||w[j][vv]==0)//必须两点都有此时枚举到的值 
					continue;
					if(w[i][uu]==w[j][vv]){//所选两值不可相等
						continue;
					}
					if(w[i][uu]==j||w[j][vv]==i) //所选两值不可等于双方 
					continue;
					maxx=max(a[i]+a[j]+a[w[i][uu]]+a[w[j][vv]],maxx);
				}
			}
		}
	}

总结

一道中位蓝,不过细节蛮多的,枚举2号4号结点以及最大值次大值次次大值的思想都很值得琢磨

posted @ 2024-10-21 16:34  健康铀  阅读(15)  评论(0编辑  收藏  举报