谁有现成的好参数啊?
/*
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;
}