85pts正解(应该是)求卡常
查看原帖
85pts正解(应该是)求卡常
643820
WangLianda楼主2022/10/30 11:49

bfs+双向搜索的思路

时间复杂度O(n^2)

主要思路是建出一张新图f:f[i][j]=1表示点i和点j在K步之内可达。

然后在图f上跑搜索,记录所有的从点1开始2步(新图上的2步)之内可以到达的点以及相关信息。复杂度O(n^2)

然后O(n^2)合并这些信息,输出答案。

双向搜索需要维护一个数组g,定义g如下:

pair<int,vector> g[2505][3][3]

其中g[i][j][k]表示以点i为末尾的一条1->i的链,链长为g(长度不包括链头1),这一条链的点权和是已知的最大值/次大值/次次大值(k=0/1/2)。

其中g[i][j][k].first存储的是点权和,g[i][j][k].second存储的是目前链上已有的点。

然后是合并的部分,枚举点i、j作为一个长度为2(不包括链头)的链的末尾,如果i、j在图f上连通,那么更新答案: 题目要求不能有重复的点,那么如果有重复的点那么答案就不合法,不能加入答案,更新答案要使用最大的合法答案。

注意到一个链上只有两个点,且保证i!=j,那么最大值/次大值/次次大值中至少有一个合法答案,分别枚举一下,更新答案即可。

注意到双向搜索复杂度大致是O(n^2×9log3),合并复杂度大致是O(n^2×9),大概是,我没仔细算。

没有看题解,时间复杂度应该是对的,自我感觉应该卡卡常能过!求大佬卡常!

#include<iostream>
#include<algorithm>
#include<queue>
#include<array>
#include<cstring>
#include<vector>
using namespace std;
#define int long long
vector<vector<int>> a;
int n,m,K;
int h[2505];
bool vis[2505];
bool f[2505][2505];
typedef pair<int,pair<int,int>> edge;
void bfs(int x) {
	vis[x]=true;
	queue<pair<int,int>> q;
	q.push(pair<int,int> {x,0});
	while(!q.empty()) {
		int u=q.front().first;
		int step=q.front().second;
		q.pop();
		f[x][u]=f[u][x]=1;
		if(step==K+1) continue;
		for(auto&v:a[u]) {
			if(vis[v]) continue;
			q.push(pair<int,int> {v,step+1});
			vis[v]=true;
		}
	}
}
int maxx;
pair<int,vector<int>> g[2505][3][3];
//g[i][j][k],表示第i个节点,目前长度为1/2,维护的是最大值/次大值/次次大值
int push(pair<int,vector<int>> x[3],pair<int,vector<int>> y) {
	vector<pair<int,vector<int>>> v;
	for(int i=0; i<3; i++)
		v.push_back(x[i]);
	v.push_back(y);
	sort(v.begin(),v.end(),greater<pair<int,vector<int>>>());
	int t=0;
	while(t<v.size()&&v[t]!=y)
		t++;
	if(t==v.size())	return -1;
//	cout<<"sort:";
	for(int i=0; i<3; i++)
		x[i]=v[i]
//		,cout<<v[i].first<<' '
		     ;
//	cout<<endl;
	return t;
}
void dfs(int u,int step,pair<int,vector<int>> w) {
	if(step==2) return ;
	for(int v=1; v<=n; v++) {
		if(f[u][v]&&u!=v&&!vis[v]) {
			auto x=w.second;
			x.push_back(v);
			int t=push(g[v][step+1],pair<int,vector<int>> {w.first+h[v],x});
//			if(~t)
//				cout<<t<<"("<<v<<','<<step+1<<")""->"<<g[v][step+1][t].first<<endl;
			vis[v]=true;
			if(~t)
				dfs(v,step+1,g[v][step+1][t]);
			vis[v]=false;
		}
	}
}
bool have_eq(vector<int>x,vector<int>y) {
	for(auto&i:x)
		for(auto&j:y)
			if(i==j)
				return true;
	return false;
}
signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>n>>m>>K;
	for(int i=0; i<=n; i++)
		a.push_back(vector<int> {});
	for(int i=2;i<=n; i++)
		cin>>h[i];
	for(int i=1; i<=m; i++) {
		int u,v;
		cin>>u>>v;
		a[u].push_back(v);
		a[v].push_back(u);
	}
	for(int i=1; i<=n; i++) {
		bfs(i);
		memset(vis,0,sizeof vis);
	}
//	for(int i=1; i<=n; i++,cout<<endl)
//		for(int j=1; j<=n; j++)
//			cout<<f[i][j]<<' ';
	vis[1]=true;
	dfs(1,0,g[0][0][0]);
	vis[1]=false;
//	for(int i=1; i<=n; i++) {
//		cout<<i<<':'<<endl;
//		for(int k=0; k<3; k++) {
//			cout<<"maxx"<<k<<':'<<g[i][2][k].first;
//			for(auto&j:g[i][2][k].second)
//				cout<<' '<<j;
//			cout<<endl;
//		}
//	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<i;j++)
			if(f[i][j])
				for(int x=0;x<3&&g[i][2][x].first;x++)
					for(int y=0;y<3&&g[j][2][y].first;y++)
						if(!have_eq(g[i][2][x].second,g[j][2][y].second))
							maxx=max(maxx,g[i][2][x].first+g[j][2][y].first);
	cout<<maxx;
	return 0;
}
2022/10/30 11:49
加载中...