codeforces1027D

题目链接

http://codeforces.com/problemset/problem/1027/D

这道题目的入手点就是图的特点。图的输入形式是 第 i 个点的后继是a[ i ],且只有一个,a[ i ]的范围是从1到n。所以图中一定存在环,并且环和环之间不可能公用一条边(如果共用一条边,那么某个点会有两个后继)。

因此这道题目就是用dfs找环,然后通过回溯求出环上定点的权值最小值。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#define DEBUG(x) cout<<#x<<" = "<<x<<endl
using namespace std;
const int MAXN=2e5+10;
int N;
vector<int>G[MAXN];
int cost[MAXN];
int vis[MAXN];
int cv=-1;
int mc;
int csum=0;
void dfs(int u)
{
    if(vis[u]==1){
        cv=u;
        mc=cost[u];
        return;
    }
    vis[u]=1;
    for(int i=0;i<G[u].size() ;i++ ){
        int v=G[u][i];
        dfs(v);
    }
    if(cv!=-1){
        if(cv==u){csum+=mc;cv=-1;}
        else mc=min(mc,cost[u]);
    }
}
int main()
{
//    freopen("in.txt","r",stdin);
    scanf("%d",&N);
    for(int i=1;i<=N ;i++ ){
        scanf("%d",&cost[i]);
    }
    for(int i=1;i<=N ;i++ ){
        int e;
        scanf("%d",&e);
        G[i].push_back(e);
    }
    for(int u=1;u<=N ;u++ ){
        if(vis[u]==0){
            dfs(u);
            cv=-1;
        }
    }
    printf("%d
",csum);
}
原文地址:https://www.cnblogs.com/MalcolmMeng/p/9528045.html