小白月赛54 F.Traveling(图论&构造)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了小白月赛54 F.Traveling(图论&构造)相关的知识,希望对你有一定的参考价值。

小白月赛54 F.Traveling(图论&构造)

显然 d 1 = d n = min ⁡ d i d_1=d_n=\\min d_i d1=dn=mindi

考虑 d i = d 1 ( m o d 2 ) d_i=d_1\\pmod 2 di=d1(mod2) i i i,可以构造 ( 1 , i , d i − d 1 2 ) (1,i,\\dfracd_i-d_12) (1,i,2did1)

接下来只需考虑 d i ≠ d 1 ( m o d 2 ) d_i\\ne d_1\\pmod2 di=d1(mod2) 的集合 S S S

我们可以选择最小的 d x d_x dx 然后连 ( 1 , x , d x − d 1 ) , ( x , n , d 1 ) (1,x,d_x-d_1),(x,n,d_1) (1,x,dxd1),(x,n,d1)

然后集合 S S S中的其他点连 ( x , i , d i − d x 2 ) (x,i,\\dfracd_i-d_x2) (x,i,2didx)

注意特判 m < n − 1 , m > n ( n − 1 ) 2 m<n-1,m>\\dfracn(n-1)2 m<n1,m>2n(n1)和构造的边数小于 m m m 和大于 m m m的情况。

不足 m m m 可以构造无效边 ( u , v , 1 e 9 ) (u,v,1e9) (u,v,1e9)

超过 m m m无解。

#include <bits/stdc++.h>
using namespace std;
const int N = 3E5 + 100, inf = 1E9;
int n, m;
int arr[N];
set<int> vis[N];
int main() 
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin >> n >> m;
	int Min = numeric_limits<int>::max();
	for (int i = 1; i <= n; i++) 
		cin >> arr[i];
		Min = min(Min, arr[i]);
	
	if (m > 1LL * n * (n - 1) / 2 || arr[1] > Min || arr[n] > Min) 
		cout << "No" << "\\n";
		return 0;
	
	vector<array<int, 3> > e;
	vector<array<int, 2> > v;
	e.push_back(1, n, Min);
	vis[1].insert(n);
	for (int i = 2; i < n; i++) 
		int d = arr[i] - arr[1];
		if (d & 1) 
			if (arr[1] == 0) 
				cout << "No" << "\\n";
				return 0;
			
			v.push_back(arr[i], i);
		 else 
			e.push_back(1, i, d / 2);
			vis[1].insert(i);
		
	
	sort(v.begin(), v.end());
	if (!v.empty()) 
		auto [d1, x] = v.front();
		auto d0 = arr[1];
		e.push_back(1, x, d1-d0);
		vis[1].insert(x);
		e.push_back(x, n, d0);
		vis[x].insert(n);
		for (int i = 1; i < v.size(); i++) 
			auto [d2, y] = v[i];
			if (x < y) 
				e.push_back(x, y, (d2 - d1) / 2);
				vis[x].insert(y);
			 else 
				e.push_back(y, x, (d2 - d1) / 2);
				vis[y].insert(x);
			
		
	
	if (m < e.size()) 
		cout << "No" << "\\n";
		return 0;
	
	for (int i = 1; i <= n && e.size() < m; i++) 
		for (int j = i + 1; j <= n && e.size() < m; j++) 
			if (vis[i].find(j) == vis[i].end()) 
				e.push_back(i, j, inf);
				vis[i].insert(j);
			
		
	
	cout << "Yes" << "\\n";
	for (auto [u, v, w] : e) 
		cout << u << " " << v << " " << w << "\\n";
	
	return 0;

以上是关于小白月赛54 F.Traveling(图论&构造)的主要内容,如果未能解决你的问题,请参考以下文章

牛客小白月赛 68 题解

UVa567_Risk(最短路)(小白书图论专题)

牛客小白月赛#67(A-D)

小白月赛-9

牛客小白月赛#69(A-E)

牛客小白月赛52