题目链接
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); }