题解 基站建设

传送门

画个图可以发现最终形成的东西是有一条公共边的两个三元环
于是求三元环是 \(O(m\sqrt m)\)
统计答案考虑枚举公共边
发现一条边参与的所有三元环中只有剩下的那个未确定的点权值最大的两个加上这条边所构成的四元环可能成为最终答案
于是对每条边开桶即可

Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 200010
#define ll long long
#define fir first
#define sec second
#define make make_pair
#define pb push_back
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, m;
int r[N];

namespace force{
	int ans;
	bool mp[510][510];
	void solve() {
		for (int i=1,u,v; i<=m; ++i) {
			u=read(); v=read();
			mp[u][v]=mp[v][u]=1;
		}
		for (int i=1; i<=n; ++i) {
			for (int j=i+1; j<=n; ++j) if (mp[i][j]) {
				for (int k=1; k<=n; ++k) if (i!=k && j!=k && mp[i][k] && mp[j][k]) {
					for (int l=k+1; l<=n; ++l) if (i!=l && j!=l && mp[i][l] && mp[j][l]) {
						ans=max(ans, (r[i]+1)*(r[j]+1)+r[k]*r[l]);
					}
				}
			}
		}
		printf("%d\n", ans);
		exit(0);
	}
}

namespace task1{
	int head[N], sta[N], size, ans, top;
	bool vis[N];
	struct edge{int to, next;}e[N<<1];
	inline void add(int s, int t) {e[++size].to=t; e[size].next=head[s]; head[s]=size;}
	void dfs(int u) {
		vis[u]=1;
		sta[++top]=r[u];
		for (int i=head[u],v; ~i; i=e[i].next) {
			v = e[i].to;
			if (!vis[v]) dfs(v);
		}
	}
	void solve() {
		memset(head, -1, sizeof(head));
		for (int i=1,u,v; i<=m; ++i) {
			u=read(); v=read();
			add(u, v); add(v, u);
		}
		for (int i=1; i<=n; ++i) if (!vis[i]) {
			top=0;
			dfs(i);
			if (top>=4) {
				sort(sta+1, sta+top+1, [](int a, int b){return a>b;});
				ans=max(ans, (sta[1]+1)*(sta[2]+1)+sta[3]*sta[4]);
			}
		}
		printf("%d\n", ans);
		exit(0);
	}
}

namespace task{
	struct tpl{int a, b, c; tpl(){} tpl(int x, int y, int z):a(x),b(y),c(z){}};
	vector<int> buc[N];
	int tim[N], deg[N], head[N], tem[N], size, top, ans;
	struct edge{int to, next;}e[200010];
	inline void add(int s, int t) {e[++size].to=t; e[size].next=head[s]; head[s]=size;}
	map<pair<int, int>, int> mp;
	pair<int, int> e2[N];
	void calc(tpl a, tpl b) {
		int tot=0;
		tem[++tot]=a.a; tem[++tot]=a.b; tem[++tot]=a.c;
		tem[++tot]=b.a; tem[++tot]=b.b; tem[++tot]=b.c;
		sort(tem+1, tem+tot+1);
		tot=unique(tem+1, tem+tot+1)-tem-1;
		if (tot!=4) return ;
		sort(tem+1, tem+tot+1, [](int a, int b){return r[a]<r[b];});
		ans=max(ans, (r[tem[4]]+1)*(r[tem[3]]+1)+r[tem[2]]*r[tem[1]]);
	}
	void solve() {
		memset(head, -1, sizeof(head));
		for (int i=1,u,v; i<=m; ++i) {
			u=read(); v=read();
			e2[i]=make(u, v);
			++deg[u]; ++deg[v];
			mp[make(min(u, v), max(v, u))]=i;
		}
		for (int i=1,u,v; i<=m; ++i) {
			u=e2[i].fir; v=e2[i].sec;
			if (deg[u]==deg[v]&&u>v) swap(u, v);
			if (deg[u]>deg[v]) swap(u, v);
			add(u, v);
		}
		for (int i=1; i<=n; ++i) {
			for (int j=head[i]; ~j; j=e[j].next) tim[e[j].to]=i;
			for (int j=head[i],u; ~j; j=e[j].next) {
				u=e[j].to;
				for (int k=head[u],v; ~k; k=e[k].next) {
					v=e[k].to;
					// if (tim[v]==i) sta[++top]=tpl(i, u, v);
					// cout<<"ring: "<<i<<' '<<u<<' '<<v<<endl;
					if (tim[v]==i) {
						buc[mp[make(min(i, u), max(i, u))]].pb(v);
						buc[mp[make(min(i, v), max(i, v))]].pb(u);
						buc[mp[make(min(v, u), max(v, u))]].pb(i);
					}
				}
			}
		}
		// for (int i=1; i<=top; ++i) 
			// for (int j=i+1; j<=top; ++j)
				// calc(sta[i], sta[j]);
		for (int i=1; i<=m; ++i) {
			sort(buc[i].begin(), buc[i].end(), [](int a, int b){return r[a]<r[b];});
			if (buc[i].size()<2) continue;
			int tot=0;
			tem[++tot]=e2[i].fir; tem[++tot]=e2[i].sec;
			tem[++tot]=buc[i][buc[i].size()-2];
			tem[++tot]=buc[i][buc[i].size()-1];
			sort(tem+1, tem+tot+1, [](int a, int b){return r[a]<r[b];});
			ans=max(ans, (r[tem[4]]+1)*(r[tem[3]]+1)+r[tem[2]]*r[tem[1]]);
		}
		printf("%d\n", ans);
		exit(0);
	}
}

signed main()
{
	freopen("station.in", "r", stdin);
	freopen("station.out", "w", stdout);

	n=read(); m=read();
	for (int i=1; i<=n; ++i) r[i]=read();
	// if (m<250) force::solve();
	// else task1::solve();
	task::solve();
	
	return 0;
}
posted @ 2021-11-07 17:05  Administrator-09  阅读(1)  评论(0编辑  收藏  举报