璟雯院

珺璟如晔,雯华若锦

用户工具

站点工具


icpc:problems:usaco22open_visits_s
problems
名称Visits S
题目编号USACO22OPEN_S1
题目链接luogu.com.cn/…
来源USACO
算法分类基环树
难易程度容易

Visits S

想法

读懂题目就会发现,题目中的P排列,其实是处理奶牛的顺序。

将每个奶牛用自身与想要到的点建边,建出的图为基环树。可以轻松发现在一个环里,无论如何排列,总会有一个牛是不能叫的。所以每个环取最小值不能叫。

代码实现

非递归版本:

#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
 
const int N = 100010;
int v[N], p[N];
long long int ans;
bool vis[N], this_vis[N];
 
int main()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; ++i) {
		cin >> v[i] >> p[i];
		ans += p[i];
	}
 
	for (int i = 1; i <= n; ++i) {
		if(!vis[i])
		{
			memset(this_vis, false, sizeof(this_vis));
			this_vis[i] = true; vis[i] = true;
			int temp = i;
			while(!this_vis[v[temp]] && !vis[v[temp]])
			{
				temp = v[temp];
				this_vis[temp] = true; vis[temp] = true;
			}
 
			if(this_vis[v[temp]])
			{
				int mi = p[temp], t = v[temp];
				do{
					mi = min(mi, p[t]);
					t = v[t];
				}while(t != temp);
				ans -= mi;
			}
		}
	}
 
	cout << ans;
	return 0;
}

递归版本:

#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
 
const int N = 100010;
int v[N], p[N];
long long int ans;
bool vis[N], this_vis[N];
 
void DFS(int x)
{
	if(this_vis[ v[x] ])
	{
		int mi = p[x], temp = v[x];
		do{
			mi = min(mi, p[temp]);
			temp = v[temp];
		}while(temp != x);
		ans -= mi;
		return ;
	}
	if(vis[ v[x] ])
		return ;
	vis[v[x]] = true;
	this_vis[v[x]] = true;
	DFS(v[x]);
	return ;
}
 
int main()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; ++i) {
		cin >> v[i] >> p[i];
		ans += p[i];
	}
 
	for (int i = 1; i <= n; ++i) {
		if(!vis[i])
		{
			memset(this_vis, false, sizeof(this_vis));
			this_vis[i] = true;
			vis[i] = true;
			DFS(i);
		}
	}
 
	cout << ans;
	return 0;
}
/app/www/public/data/pages/icpc/problems/usaco22open_visits_s.txt · 最后更改: 2023/02/09 09:57 由 温婕莺