模拟退火求调,每次都稳定WA#18和Hack,是否参数外还有别的问题
查看原帖
模拟退火求调,每次都稳定WA#18和Hack,是否参数外还有别的问题
470960
Yellow_and_Strong楼主2023/3/30 08:14

rt,悬赏关注

#include <bits/stdc++.h>
#define INF 0x7fffffff
#define double long double

using namespace std;

const int MAXN = 60;

const int T_0 = 1000;
const int T_k = 1e-10;
const int d = 0.99995;

inline int read()
{
    int x = 0; char ch = getchar();
    while (!isdigit(ch)) ch = getchar();
    while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch xor 48), ch = getchar();
    return x;
}
inline void write (int x)
{
    if (x > 9) write(x / 10);
    putchar (x % 10 + 48);
}

int n, m, k, V[MAXN]; bool flag[MAXN]; int have[MAXN], no, _no[MAXN];
struct Edge { int to, val, next; }e[MAXN << 1]; int head[MAXN], cnt;
inline void add (int u, int v, int w) { e[++ cnt] = (Edge){v, w, head[u]}, head[u] = cnt; }
inline void input()
{
    n = read(), m = read(), k = read();
    for (register int i = 1; i <= n; ++ i) V[i] = read() + 1;
    for (register int u = 1, w; u <= n; ++ u)
        w = read(), add(u, V[u], w), add(V[u], u, w);
    for (register int i = 1, x; i <= m; ++ i)
        x = read() + 1, flag[x] = true, have[i] = x;
}

int ans, dis[MAXN]; bool vis[MAXN];
struct Node
{
    int id, dis;
    friend bool operator < (Node x, Node y)
        { return x.dis > y.dis; }
};
inline int calc()
{
    priority_queue <Node> q;
    for (register int i = 1; i <= n; ++ i) vis[i] = false, dis[i] = INF;
    for (register int i = 1; i <= m; ++ i)
        dis[have[i]] = 0, q.push((Node){have[i], dis[have[i]]});
    for (register int i = 1; i <= min(k, no); ++ i)
        dis[_no[i]] = 0, q.push((Node){_no[i], dis[_no[i]]});
    while (!q.empty())
    {
        int u = q.top().id; q.pop();
        if (vis[u]) continue;
        vis[u] = true;
        for (register int i = head[u]; i; i = e[i].next)
        {
            int v = e[i].to;
            if (dis[u] + e[i].val < dis[v])
                dis[v] = dis[u] + e[i].val, q.push((Node){v, dis[v]});
        }
    }
    int res = 0;
    for (register int i = 1; i <= no; ++ i)
        res = max(res, dis[_no[i]]);
    ans = min(ans, res);
    return res;
}
inline void init()
{
    for (register int i = 1; i <= n; ++ i)
        if (!flag[i]) _no[++ no] = i;
    ans = calc();
    if (no == k) { write(ans), putchar('\n'); exit(0); }
}

inline double Rand() { return (double)(rand()) / RAND_MAX; }
inline void SA()
{
    double T = T_0;
    int now = ans;
    while (T > T_k)
    {
        int x = rand() % k + 1, y = rand() % (no - k) + k + 1;
        swap (_no[x], _no[y]);
        int nxt = calc();
        double delta = nxt - now;
        if (exp(-delta / T) > Rand()) now = nxt;
        else swap(_no[x], _no[y]);
        T *= d;
    }
}

inline void output() { write(ans), putchar('\n'); }

int main()
{
    srand (time(0));
    input();
    init();
    while ((double)(clock()) / CLOCKS_PER_SEC < 0.795) SA();
    output();
    return 0;
}
2023/3/30 08:14
加载中...