[ABC256E] Takahashi's Anguish 题解

[ABC256E] Takahashi's Anguish Solution

更好的阅读体验戳此进入

题面

存在 $ n $ 个人,你需要确定一个序列 $ P_n $ 表示这 $ n $ 个人的排列,对于每个人,第 $ i $ 个人有且仅有一个 $ x_i $,表示不喜欢 $ x_i $ 站在 $ i $ 的前面,若 $ x_i $ 站在 $ i $ 的前面则会产生 $ c_i $ 的不愉悦值,你需要确定排列以最小化不愉悦值之和,求最小值。

Solution

这道题想到方法之后就很简单了,是一道图论建模题。考虑将不喜欢的关系抽象成一条有向边,不难发现每个点都有且仅有一条出边,则最后形成的图在形态上一定类似一个基环树森林,或者说在形成的图中每一个连通块内最多含有一个环。

不难想到对于无环的一定有合法方案使得每一个点都不会有不喜欢的在其之前,对于环上的则一定至少需要破坏一条环上的边。于是我们跑一个类似拓朴排序的东西即可,对于无环的直接丢弃,有环的在环上找到边权最小的一条边保留即可。

Code

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>

#define PI M_PI
#define E M_E
#define npt nullptr
#define SON i->to
#define OPNEW void* operator new(size_t)
#define ROPNEW(arr) void* Edge::operator new(size_t){static Edge* P = arr; return P++;}

using namespace std;

mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int x){return rndd(1, 100) <= x;}

typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
typedef long double ld;

template < typename T = int >
inline T read(void);

struct Edge{
    Edge *nxt;
    int to;
    int val;
    OPNEW;
}ed[210000];
ROPNEW(ed);
Edge* head[210000];

int N;
bitset < 210000 > vis;
int ind[210000];
ll ans(0);

int main(){
    N = read();
    for(int i = 1; i <= N; ++i){
        int s = i, t = read();
        head[s] = new Edge{head[s], t};
        ++ind[t];
    }for(int i = 1; i <= N; ++i)head[i]->val = read();
    queue < int > cur;
    for(int i = 1; i <= N; ++i)if(!ind[i])vis[i] = true, cur.push(i);
    while(!cur.empty()){
        int tp = cur.front(); cur.pop();
        for(auto i = head[tp]; i; i = i->nxt){
            --ind[SON];
            if(!ind[SON])vis[SON] = true, cur.push(SON);
        }
    }
    for(int i = 1; i <= N; ++i){
        if(!vis[i]){
            int mn(INT_MAX);
            vis[i] = true;
            auto cur = head[i];
            while(cur->to != i){
                vis[cur->to] = true;
                mn = min(mn, cur->val);
                cur = head[cur->to];
            }mn = min(mn, cur->val);
            ans += mn;
        }
    }printf("%lld\n", ans);
    fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}

template < typename T >
inline T read(void){
    T ret(0);
    int flag(1);
    char c = getchar();
    while(c != '-' && !isdigit(c))c = getchar();
    if(c == '-')flag = -1, c = getchar();
    while(isdigit(c)){
        ret *= 10;
        ret += int(c - '0');
        c = getchar();
    }
    ret *= flag;
    return ret;
}

UPD

update-2022_12_08 初稿

posted @ 2023-01-07 15:39  Tsawke  阅读(36)  评论(0)    收藏  举报