【模擬試題】旅行
阿新 • • 發佈:2021-08-23
Description
X先生來到了一個奇怪的國家旅行。這個國家有N個城市,每個城市均有且僅有一個機場,但是這機場所有航班只飛往一個城市。每個城市有一個遊覽價值,第i個城市的遊覽價值為A[i]。
現在他想知道,從第i個城市出發,並只坐飛機飛往下一個城市,遊覽價值之和最多是多少(一個城市遊覽多次只計算1次遊覽價值)
Input
輸入檔案travel.in的第1行為一個正整數N。
第2行有N個非負整數A[i],表示了每個城市的遊覽價值。
第3行有N個正整數F[i],表示第i個城市的航班飛往的城市為F[i],可能出現F[i]=i的情況。
Output
輸出檔案travel.out包括N行,第i行包含一個非負整數,表示從第i個城市出發遊覽價值之和的最大值為多少。
Sample Input
8
5 4 3 2 1 1 1 1
2 3 1 1 2 7 6 8
Sample Output
12
12
12
14
13
2
2
1
思路
- tarjan縮點然後拓撲序,完了
- 看起來沒有c++程式碼的題解,來發一篇
程式碼
#include <iostream> #include <cstdio> #include <vector> #include <queue> using namespace std; const int maxn=200003; queue<int> q; vector<int> e[maxn]; int n,nxt[maxn],val[maxn],cnt,num,w[maxn],r[maxn]; int dfn[maxn],low[maxn],top,vis[maxn],s[maxn],bel[maxn]; void tarjan(int x){ dfn[x]=low[x]=++cnt,vis[x]=1,s[++top]=x; int v=nxt[x]; if(!dfn[v]) tarjan(v),low[x]=min(low[x],low[v]); else if(vis[v]) low[x]=min(low[x],dfn[v]); if(dfn[x]==low[x]){ ++num; do{vis[s[top]]=0,w[num]+=val[s[top]],bel[s[top--]]=num;}while(x!=s[top+1]); } } int main() { scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&val[i]); for(int i=1;i<=n;++i) scanf("%d",&nxt[i]); for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;++i) if(bel[i]!=bel[nxt[i]]) ++r[bel[i]],e[bel[nxt[i]]].push_back(bel[i]); for(int i=1;i<=num;++i) if(!r[i]) q.push(i); while(!q.empty()){ int x=q.front(); q.pop(); for(int i=0;i<e[x].size();++i){ if(!--r[e[x][i]]) q.push(e[x][i]); w[e[x][i]]+=w[x]; } } for(int i=1;i<=n;++i) cout<<w[bel[i]]<<'\n'; return 0; }