比赛链接:

https://ac.nowcoder.com/acm/contest/31454

A.So I'll Max Out My Constructive Algor...

题意:

给定一个 \(n * n\) 的迷宫,每个点有一个高度,选择一个点开始,遍历所有点,要求这条路径满足所有点仅且只能遍历一次,同时这条路径向上走(即从高度的地方走到高度高的地方)的次数小于等于向下走的次数。

思路:

随便找一条遍历所有点的路径,如果满足条件则输出,否则反向输出即可。

代码:

#include <bits/stdc++.h>
using namespace std;
using LL = long long;
void solve(){
	int n;
	cin >> n;
	vector < vector <int> > a(n, vector<int>(n));
	for (int i = 0; i < n; i ++ )
		for (int j = 0; j < n; j ++ )
			cin >> a[i][j];
	vector <int> path;
	for (int i = 0; i < n; i ++ ){
		if (i & 1){
			for (int j = 0; j < n; j ++ )
				path.push_back(a[i][j]);
		}
		else{
			for (int j = n - 1; j >= 0; j -- )
				path.push_back(a[i][j]);
		}
	}
	int cnt = 0;
	for (int i = 1; i < path.size(); i ++ ){
		if (path[i - 1] < path[i]) cnt -- ;
		else cnt ++ ;
	}
	if (cnt < 0) reverse(path.begin(), path.end());
	for (int i = 0; i < path.size(); i ++ )
		cout << path[i] << " \n"[i == path.size() - 1];
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int T;
	cin >> T;
	while(T -- ){
		solve();
	}
	return 0;
}

C.Laser Trap

题意:

在一个坐标系中已知 \(n\) 个点,任意两点间有一条线,从(0,0)出发,想到正无穷去,不能经过任何线或者点,问最少删除几个点才能到正无穷。

思路:

容易发现,将一个方向的半圆点保存之后(即将其它点删除),就可以逃出去了。
将所有坐标的反正切值进行排序,通过双指针去寻找最小值。

代码:

#include <bits/stdc++.h>
using namespace std;
using LL = long long;
const long double pi = acosl(-1);
void solve(){
	int n;
	cin >> n;
	vector<long double> a(2 * n);
	for (int i = 0; i < n; i ++ ){
		long double x, y;
		cin >> x >> y;
		a[i] = atan2l(y, x);
	}
	sort(a.begin(), a.begin() + n);
	for (int i = 0; i < n; i ++ )
		a[i + n] = a[i] + 2 * pi;
	int ans = n;
	for (int i = 0, j = 0; i < n; i ++ ){
		while(j < 2 * n && a[j] - a[i] < pi)
			j ++ ;
		ans = min(ans, j - i - 1);
	}
	cout << ans << "\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int T = 1;
	cin >> T;
	while(T -- ){
		solve();
	}
	return 0;
}

F.Sandpile on Clique

题意:

有一个完全图,每个点上有一个权值,当某个点权值大于与它相连的边时,它可以失去与边数相同的权值,然后给每一个连通的点分配 1 的权值,问图上每个点点的权值最后会不会趋于一个值不变,如果会,输出最后每一个点的权值,否则输出 "Recurrent"。

思路:

如果会趋于一个值,最多不超过 \(n - 2\) 次分配,如果超过了,说明会有一个新的点可以进行分配了,那么就会无限分配下去。
通过优先队列,每次将权值最大的那个点进行分配即可。

代码:

#include <bits/stdc++.h>
using namespace std;
using LL = long long;
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int n;
	cin >> n;
	priority_queue<pair<int, int>> q;
	vector <int> a(n);
	for (int i = 0; i < n; i ++ ){
		cin >> a[i];
		q.push({a[i], i});
	}
	for (int i = 0; i < n - 1; i ++ ){
		auto [x, id] = q.top();
		q.pop();
		if (x + i < n - 1){
			for (int j = 0; j < n; j ++ )
				cout << a[j] + i << " \n"[j == n - 1];
			return 0;
		}
		a[id] -= n;
		q.push({a[id], id});
	}
	cout << "Recurrent\n";
	return 0;
}

K.Link-Cut Tree

题意:

\(n\) 个点 \(m\) 条边的无向图,第 \(i\) 条边的长度为 \(2^i\),找到一个长度最小的环,从小到达输出构成这个环的边。

思路:

根据贪心的思路,依次向图中加入边,当出现一个环的时候,这个环就是长度最小的那个,判断环可以通过并查集去做,找环可以通过拓扑。

代码:

#include <bits/stdc++.h>
using namespace std;
using LL = long long;
struct dsu{
	int n;
	vector <int> p;
	dsu(int n) : n(n){
		p.resize(n + 1);
		iota(p.begin(), p.end(), 0);
	}
	int get(int x){
		return (x == p[x] ? x : (p[x] = get(p[x])));
	}
	void unite(int x, int y){
		x = get(x);
		y = get(y);
		if (x < y) swap(x, y);
		if (x != y){
			p[x] = y;
		}
	}
};
void solve(){
	int n, m;
	cin >> n >> m;
	vector < array<int, 2> > e(m);
	for (int i = 0; i < m; i ++ )
		cin >> e[i][0] >> e[i][1];
	dsu d(n);
	vector < vector < pair<int, int> > > G(n + 1);
	vector <int> deg(n + 1);
	set <int> s;
	auto topo = [&](){
		queue <int> q;
		for (int i = 1; i <= n; i ++ )
			if (deg[i] == 1)
				q.push(i);
		while(!q.empty()){
			int u = q.front();
			q.pop();
			for (auto [v, id] : G[u]){
				if (s.count(id)) s.erase(id);
				deg[u] -- ;
				if ( -- deg[v] == 1){
					q.push(v);
				}
			}
		}
		vector <int> ans;
		for (auto x : s)
			ans.push_back(x);
		for (int j = 0; j < ans.size(); j ++ )
			cout << ans[j] << " \n"[j == ans.size() - 1];
	};
	for (int i = 0; i < m; i ++ ){
		auto [u, v] = e[i];
		G[u].push_back({v, i + 1});
		G[v].push_back({u, i + 1});
		deg[u] ++ ;
		deg[v] ++ ;
		s.insert(i + 1);
		if (d.get(u) == d.get(v)){
			topo();
			return;
		}
		d.unite(u, v);
	}
	cout << "-1\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int T;
	cin >> T;
	while(T -- ){
		solve();
	}
	return 0;
}
posted on 2022-10-08 15:18  Hamine  阅读(209)  评论(0编辑  收藏  举报