abc256_e Takahashi's Anguish 题解

Takahashi's Anguish

题意

\(n\) 个人,每个人都有一个看不惯的人,第 \(i\) 个人看不惯 \(x_i\),如果 \(x_i\) 站在 \(i\) 的前面,则会产生 \(c_i\) 的不愉悦值。

求一个排列顺序,使得产生的不愉悦值最小,求最小值。

思路

做题之前先推样例。——鲁迅

其实带点模板的意味,每次建立一条从 \(x_i\)\(i\) 的边,边权为 \(c_i\),那么样例就是这样:

能够发现,样例的答案来源于那条用红笔圈出来的边,思路也很明显了,对于不构成环的一些边来说,必然存在一种排列方法使得这些人不会不愉悦;而对于一个环呢?它必然会使得某个人不愉悦,只要把那个边权最小的加到答案即可。

Code

点击查看代码
#include <iostream>
#include <vector>

using namespace std;
using pr = pair<int, int>;
using ll = long long;

const int N = 2e5 + 10;

int n, a[N], c, f[N], stk[N], top; // stack 维护环上边的权值
vector<pr> v[N];
ll ans;

void dfs (int x) {
  if (f[x]) {
    if (f[x] == 1) { // 判断构成环
      int sum = 1e9 + 10;
      for (int i = 0; i < top; i++) {
        sum = min(sum, stk[i]); // 选择边权最小值,加入答案
      }
      ans += sum;
    }
    return ;
  }
  f[x] = 1; // 标记在环上
  for (pr i : v[x]) {
    stk[top++] = i.second; // 将边权压入栈
    dfs(i.first);
    top--; // 弹出栈顶
  }
  f[x] = 2; // 标记不在环上但走过这个点
}

int main () {
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
  }
  for (int i = 1; i <= n; i++) {
    cin >> c;
    v[a[i]].push_back({i, c}); // 建图
  }
  for (int i = 1; i <= n; i++) {
    dfs(i); // 对每个点都要经行遍历
  }
  cout << ans;
  return 0;
}
posted @ 2023-05-17 18:00  wnsyou  阅读(13)  评论(0编辑  收藏  举报