(若是不會tarjan的請點擊這兒)html
你須要的東西: (1)、dfn[],表示這個點在dfs時是第幾個被搜到的。 (2)、low[],表示這個點以及其子孫節點連的全部點中dfn最小的值 (3)、stack[],表示當前全部可能能構成是強連通份量的點。 (4)、vis[],表示一個點是否在stack中。 (5)、color[],記錄每個點強連通份量的編號。 (6)、deep,記錄dfs樹的深度 inline void tarjan(int now) { dfn[now]=++deep; low[now]=deep; vis[now]=1; st.push(now); for(int i=0;i<ver[now].size();i++) { int x=ver[now][i]; if(!dfn[x]) { tarjan(x); low[now]=min(low[now],low[x]); } else { if(vis[x]) low[now]=min(low[now],low[x]); } } if(dfn[now]==low[now]) { color[now]=++sum; vis[now]=0; while(st.top()!=now) { color[st.top()]=sum; vis[st.top()]=0; st.pop(); } st.pop(); } }
//重點:這裏建新圖是依託強連通份量的編號來建的 for(int i=1;i<=n;i++) { for(int j=0;j<ver[i].size();j++) { int x=ver[i][j]; if(color[i]!=color[x])//若是不是屬於同一個強連通份量中,那麼就合併 { g[color[i]].push_back(color[x]); //千萬不能寫成g[i].push_back(x);坑死我了 } } } //這一部分代碼還能夠適當優化...(想想)
for(int i=1;i<=n;i++) { ww[color[i]]+=w[i];//將這個強連通份量中全部的點權所有加起來 if(tf[i])tf[color[i]]=1;//只要這個強連通份量中有一個結點有酒館,那麼就設定爲有酒館 }
//模板不作解釋 inline void spfa() { d[color[s]]=ww[color[s]]; queue<int>q; q.push(color[s]); while(q.size()) { int now=q.front(); q.pop(); for(int i=0;i<g[now].size();i++) { int x=g[now][i]; if(d[now]+ww[x]>d[x]) { d[x]=d[now]+ww[x]; q.push(x); } } } }
因此...c++
在全部有酒館的節點中選一個最大值輸出就行了優化
for(int i=1;i<=sum;i++) { //cout<<d[i]<<" "; if(tf[i])ans=max(ans,d[i]); }
完整代碼spa
#include<bits/stdc++.h> using namespace std; const int MAXN=500000+10; int n,m; vector<int>ver[MAXN]; vector<int>g[MAXN]; int w[MAXN],ww[MAXN]; bool tf[MAXN]; int s,p,ans=0; int dfn[MAXN],color[MAXN],low[MAXN]; int deep,sum; bool vis[MAXN]; int d[MAXN]; stack<int>st; inline int read() { int tot=0; char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') { tot=tot*10+c-'0'; c=getchar(); } return tot; } inline void tarjan(int now) { dfn[now]=++deep; low[now]=deep; vis[now]=1; st.push(now); for(int i=0;i<ver[now].size();i++) { int x=ver[now][i]; if(!dfn[x]) { tarjan(x); low[now]=min(low[now],low[x]); } else { if(vis[x]) low[now]=min(low[now],low[x]); } } if(dfn[now]==low[now]) { color[now]=++sum; vis[now]=0; while(st.top()!=now) { color[st.top()]=sum; vis[st.top()]=0; st.pop(); } st.pop(); } } inline void spfa() { d[color[s]]=ww[color[s]]; queue<int>q; q.push(color[s]); while(q.size()) { int now=q.front(); q.pop(); for(int i=0;i<g[now].size();i++) { int x=g[now][i]; if(d[now]+ww[x]>d[x]) { d[x]=d[now]+ww[x]; q.push(x); } } } } int main() { //freopen("testdata.in","r",stdin); n=read();m=read(); for(int i=1;i<=m;i++) { int x=read(),y=read(); ver[x].push_back(y); } for(int i=1;i<=n;i++) w[i]=read(); s=read();p=read(); for(int i=1;i<=p;i++) { int x=read(); tf[x]=1; } for(int i=1;i<=n;i++) { if(!dfn[i]) tarjan(i); } /*cout<<endl; for(int i=1;i<=n;i++) cout<<color[i]<<" "; cout<<endl;*/ for(int i=1;i<=n;i++) { for(int j=0;j<ver[i].size();j++) { int x=ver[i][j]; if(color[i]!=color[x]) { //cout<<i<<" "<<x<<" "<<color[i]<<" "<<color[x]<<endl; g[color[i]].push_back(color[x]); } } } for(int i=1;i<=n;i++) { ww[color[i]]+=w[i]; if(tf[i])tf[color[i]]=1; } /*cout<<color[s]<<endl; cout<<endl; for(int i=1;i<=sum;i++) { for(int j=0;j<g[i].size();j++)cout<<i<<" "<<g[i][j]<<"\n"; } cout<<endl; for(int i=1;i<=sum;i++) cout<<ww[i]<<" ";cout<<endl; for(int i=1;i<=sum;i++) cout<<tf[i]<<" ";cout<<endl; cout<<ww[color[s]]<<endl;*/ spfa(); for(int i=1;i<=sum;i++) { //cout<<d[i]<<" "; if(tf[i])ans=max(ans,d[i]); } //cout<<endl; cout<<ans<<endl; return 0; }