題目鏈接:毒瘤之神祕通道
因爲邊權和之前通過的人數有關,所以我們需要先一遍拓撲求出邊權。
然後第二次拓撲求出dp[i]以i爲起點到0的答案。
AC代碼:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;
int n,m,to[N],w[N],dp[N],res=-1,a[N],deg[N];
int dfs(int x){
if(!x) return 0;
if(dp[x]) return dp[x];
return dp[x]=w[x]+dfs(to[x]);
}
signed main(){
cin>>n>>m; queue<int> q;
for(int i=1;i<=n;i++) scanf("%lld",&to[i]),deg[to[i]]++;
for(int i=1,x;i<=m;i++) scanf("%lld %lld",&a[i],&x),w[a[i]]+=x;
for(int i=1;i<=n;i++) if(!deg[i]) q.push(i);
while(q.size()){
int u=q.front(); q.pop();
if(--deg[to[u]]==0) q.push(to[u]);
w[to[u]]+=w[u];
}
for(int i=1;i<=n;i++) dfs(a[i]);
for(int i=1;i<=m;i++)
if(res==-1||dp[a[i]]<dp[res]||(dp[a[i]]==dp[res]&&a[i]>res)) res=a[i];
cout<<res<<' '<<dp[res];
return 0;
}