99pts求条
查看原帖
99pts求条
411141
alpharchmage楼主2024/11/10 17:42

谁有现成的好参数啊?

/*
1.能否二分答案?
2.可以倒着思考问题?
3.打一个小表
4.寻找结论
5.是DP & 记忆化搜索吗?
6.是否有单调性?
7.注意取模(数字写没写错 , 是否取了模)
8.能否tarjan缩个点?
9.用一下莫队?
*/
#include<bits/stdc++.h>
using namespace std;
mt19937 rng(0x07210d00);
double Begin = 100000 , End = 1e-5 , D = 0.999;
int n = 0 , m = 0 , k = 0 , cnt = 0 , tot = 0 , ans = INT_MIN , tmp_ans = 0;
array<int , 5000> vis , dis , head;
array<int , 5000> tag , key , used;
struct Node{
	int to;
	int nxt;
	int val;
};
struct Point{
	int id;
	int path;
};
bool operator < (const Point &x , const Point &y)
{
	return x.path < y.path;
}
bool operator > (const Point &x , const Point &y)
{
	return x.path > y.path;
}
priority_queue<Point , vector<Point> , greater<Point> > q;
array<Node , 20010> edge;
void new_line(int a , int b , int c)
{
	edge[++ cnt].to = b;
	edge[cnt].val = c;
	edge[cnt].nxt = head[a];
	head[a] = cnt;
	return;
}
void dijkstra()
{
	dis.fill(1e9);
	used.fill(false);
	for(int i = 1;i <= n;++ i) if(vis[i]) q.push({i , 0}) , dis[i] = 0;
	for(int i = 1;i <= min(tot , k);++ i) q.push({tag[i] , 0}) , dis[tag[i]] = 0;
	while(!q.empty())
	{
		int x = q.top().id;
		q.pop();
		if(used[x]) continue;
		used[x] = true;
		for(int e = head[x];e;e = edge[e].nxt)
		{
			int to = edge[e].to;
			if(dis[to] > dis[x] + edge[e].val)
			{
				dis[to] = dis[x] + edge[e].val;
				q.push({to , dis[to]});
			}
		}
	}
}
array<int , 50010> to , val;
void SA()
{
	double Now = Begin;
	while(Now > End)
	{
		int x = rng() % k + 1, y = rng() % (tot - k) + k + 1;
		swap(tag[x] , tag[y]);
		dijkstra();
		tmp_ans = INT_MIN;
		for(int i = 1;i <= n;++ i) tmp_ans = max(tmp_ans , dis[i]);
		int delta = tmp_ans - ans;
		if(delta < 0 ||  exp(- delta * 1.0 / Now) * 1.0 * RAND_MAX > rng() * 1.0) ans = tmp_ans;
		else swap(tag[x] , tag[y]);
		Now *= D;
	}
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cin >> n >> m >> k;
	for(int i = 1;i <= n;++ i) cin >> to[i] , ++ to[i];
	for(int i = 1;i <= n;++ i) cin >> val[i];
	for(int i = 1;i <= n;++ i)
	{
		new_line(i , to[i] , val[i]);
		new_line(to[i] , i , val[i]);
	}
	for(int i = 1;i <= m;++ i)
	{
		int tmp = 0;
		cin >> tmp;
		++ tmp;
		vis[tmp] = true;
	}
	for(int i = 1;i <= n;++ i)
	{
		if(!vis[i]) tag[++ tot] = i;
	}
	dijkstra();
	for(int i = 1;i <= n;++ i) ans = min(ans , dis[i]);
	if(tot - k == 0)
	{
		cout << 0 << endl;
		return 0;
	}
	while(clock() * 1.0 / CLOCKS_PER_SEC < 0.75) SA();
	cout << ans << endl;
	return 0;
}
2024/11/10 17:42
加载中...