题目链接:毒瘤之神秘通道
因为边权和之前通过的人数有关,所以我们需要先一遍拓扑求出边权。
然后第二次拓扑求出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;
}