Codeforces Round #625 (Div. 2, based on Technocup 2020 Final Round)


比赛链接:

https://codeforces.com/contest/1321

C. Remove Adjacent

题目大意:

给定一个字符串,当相邻的两个字符之间差值小于 1 的时候,可以删除他们中的任何一个,问最多能删除多少个字符。

思路:

最优的策略肯定是删除最大的先,所以从大到小枚举每一个字符,判断每一个字符能不能删除,能删除就删掉,然后从头开始重新判断。

代码:

#include 
using namespace std;
int n;
string s;
int main(){
	cin >> n >> s;
	for (char ch = 'z'; ch >= 'a'; ch -- ){
		for (int i = 0; i < s.size(); i ++ ){
			if (ch == s[i]){
				if (i > 0 && abs(s[i] - s[i - 1]) == 1){
					s.erase(s.begin() + i);
					i = -1;
				}
				else if (i < n - 1 && abs(s[i] - s[i + 1]) == 1){
					s.erase(s.begin() + i);
					i = -1;
				}
			}
		}
	}
	cout << n - s.size() << "\n";
	return 0;
}

D. Navigation System

题目大意:

给定一张有向图,图上任意两点之间保证可以到达,现在从 \(s\)\(t\),导航系统会给定一条最短路径,如果不按这个最短路径走,那么导航系统会重新规划最优的路径。现在已知从 \(s\)\(t\) 的一个路径,问导航系统最少和最多重新规划几次路线。

思路:

首先通过 \(bfs\) 求出每个点到终点的最短路径,将边的方向反一下去 \(bfs\) 就行。
当到的下一个点的距离大于当前点 - 1 时,说明不是最短路径,那么一定要重新规划路线。
当到的下一个点的距离等于当前点 - 1 时,如果有好几条最短路径,可以重新规划路径。

代码:

#include 
using namespace std;
const int N = 2e5 + 10;
int n, m, k;
vector  g[N], G[N], p(N), d(N);
void bfs (){
	queue  q;
	q.push(p[k]);
	while (q.size()){
		int u = q.front();
		q.pop();
		for (auto v : g[u]){
			if (v == p[k]) continue;
			if (d[v]) continue;
			d[v] = d[u] + 1;
			q.push(v);
		}
	}
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	cin >> n >> m;
	for (int i = 1; i <= m; i ++ ){
		int u, v;
		cin >> u >> v;
		G[u].push_back(v);
		g[v].push_back(u);
	}
	cin >> k;
	for (int i = 1; i <= k; i ++ ){
		cin >> p[i];
	}
	bfs();
	int mn = 0, mx = 0;
	for (int i = 1; i < k; i ++ ){
		if (d[p[i + 1]] > d[p[i]] - 1){
			mn ++ ;
			mx ++ ;
		}
		else {
			int ok = 0;
			for (auto j : G[p[i]]){
				if (d[j] == d[p[i]] - 1 && j != p[i + 1]){
					ok = 1;
					break;
				}
			}
			mx += ok;
		}
	}
	cout << mn << " " << mx << "\n";
	return 0;
}