「SP14887」 GOODA

题意

给定一个 \(n\) 个点 \(m\) 条边的有向图,每个点都有点权,求一条从 \(S\) 到 \(E\) 的路径,使路径经过的点权值之和最大。

可以多次经过一条边或者一个点,但每个点的权值最多计算一次。

分析

P3387 很像。

对原图缩点后得到一张 DAG,然后在图上跑类似最短路,实际是拓扑的东西就可以了。

复杂度大概是 \(O(n)\)

Code

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
#define dbg(x) cout<<#x<<": "<<x<<"\n"
// static char buf[100],*p1=buf,*p2=buf,obuf[100],*p3=obuf;
// #define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,100,stdin),p1==p2)?EOF:*p1++
// #define putchar(x) (p3-obuf<100)?(*p3++=x):(fwrite(obuf,p3-obuf,1,stdout),p3=obuf,*p3++=x)
inline ll read(){ll x=0,f=1;char c=getchar();while(c<48||c>57){if(c==45)f=0;c=getchar();}while(c>47&&c<58)x=(x<<3)+(x<<1)+(c^48),c=getchar();return f?x:-x;}
inline void write(ll x){if(!x){putchar(48);putchar('\n');return;}short top=0,s[40];if(x<0)x=-x,putchar(45);while(x)s[top++]=x%10^48,x/=10;while(top--)putchar(s[top]);putchar('\n');}
mt19937_64 rnd(chrono::system_clock::now().time_since_epoch().count());
const ll mod=998244353,maxn=2e5+5,maxt=505;
ll n,m,s,e,frm[maxn],to[maxn],a[maxn],dfn[maxn],low[maxn],tot,col[maxn],cnt,siz[maxn],f[maxn];
bool vis[maxn];
stack<ll>st;
vector<ll>son[maxn];
inline void tarjan(ll u){
dfn[u]=low[u]=++tot,vis[u]=1,st.push(u);
for(auto v:son[u]){
if(!dfn[v])tarjan(v),low[u]=min(low[u],low[v]);
else if(vis[v])low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
++cnt;
while(st.top()!=u)col[st.top()]=cnt,siz[cnt]+=a[st.top()],vis[st.top()]=0,st.pop();
col[u]=cnt,siz[cnt]+=a[u],vis[u]=0,st.pop();
}
}
inline void dfs(ll u){
if(f[u])return;
f[u]=siz[u];
ll mx=0;
for(auto v:son[u]){
if(!f[v])dfs(v);
mx=max(mx,f[v]);
}
f[u]+=mx;
}
inline void solve(){
n=read(),m=read(),s=read(),e=read();
for(ll i=1;i<=n;++i)a[i]=read();
for(ll i=1;i<=m;++i){
frm[i]=read(),to[i]=read();
son[frm[i]].push_back(to[i]);
}
for(ll i=1;i<=n;++i)if(!dfn[i])tarjan(i);
for(ll i=1;i<=n;++i)son[i].clear();
for(ll i=1;i<=m;++i){
if(col[frm[i]]!=col[to[i]]){
son[col[frm[i]]].push_back(col[to[i]]);
}
}
memset(vis,0,sizeof(vis));
queue<ll>q;q.push(col[s]),vis[col[s]]=1,f[col[s]]=siz[col[s]];
while(!q.empty()){
ll u=q.front();q.pop();vis[u]=0;
for(auto v:son[u]){
f[v]=f[u]+siz[v];
if(!vis[v])vis[v]=1,q.push(v);
}
}
write(f[col[e]]);
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ll t=1;
while(t--){
solve();
}
// fwrite(obuf,p3-obuf,1,stdout);
return 0;
}
posted @   run-away  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示