1 条题解

  • 0
    @ 2026-10-25 22:58:50

    思路

    同一SCC能绕行取完所有点权,缩点为DAG后从起点做点权最长路,仅可达酒吧可作为终点;不能把所有可达分支的钱相加或重复计算ATM,50万规模使用迭代遍历与紧凑邻接存储,金额可达20亿。

    参考程序(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    int main(){ios::sync_with_stdio(false);cin.tie(nullptr);int n,m;cin>>n>>m;vector<int>from(m),to(m),h(n+1),rh(n+1);for(int i=0;i<m;i++){cin>>from[i]>>to[i];--from[i];--to[i];h[from[i]+1]++;rh[to[i]+1]++;}for(int i=1;i<=n;i++){h[i]+=h[i-1];rh[i]+=rh[i-1];}vector<int>g(m),rev(m);{auto at=h,rat=rh;for(int i=0;i<m;i++){g[at[from[i]]++]=to[i];rev[rat[to[i]]++]=from[i];}}vector<unsigned char>seen(n);vector<int>next=h,order,st;order.reserve(n);st.reserve(n);for(int s=0;s<n;s++)if(!seen[s]){seen[s]=1;st.push_back(s);while(!st.empty()){int u=st.back();if(next[u]<h[u+1]){int v=g[next[u]++];if(!seen[v]){seen[v]=1;st.push_back(v);}}else{order.push_back(u);st.pop_back();}}}vector<int>comp(n,-1);int count=0;for(auto it=order.rbegin();it!=order.rend();++it)if(comp[*it]<0){comp[*it]=count;st.push_back(*it);while(!st.empty()){int u=st.back();st.pop_back();for(int at=rh[u];at<rh[u+1];at++){int v=rev[at];if(comp[v]<0){comp[v]=count;st.push_back(v);}}}count++;}vector<int>().swap(g);vector<int>().swap(rev);vector<int>().swap(h);vector<int>().swap(rh);vector<int>().swap(next);vector<int>().swap(order);vector<int>().swap(st);vector<unsigned char>().swap(seen);vector<long long>money(count);for(int i=0;i<n;i++){int cash;cin>>cash;money[comp[i]]+=cash;}int S,P;cin>>S>>P;--S;vector<unsigned char>pub(count);while(P--){int v;cin>>v;pub[comp[v-1]]=1;}vector<int>head(count+1),degree(count);int edges=0;for(int i=0;i<m;i++)if(comp[from[i]]!=comp[to[i]]){head[comp[from[i]]+1]++;degree[comp[to[i]]]++;edges++;}for(int i=1;i<=count;i++)head[i]+=head[i-1];vector<int>dag(edges);{auto at=head;for(int i=0;i<m;i++)if(comp[from[i]]!=comp[to[i]])dag[at[comp[from[i]]]++]=comp[to[i]];}vector<int>().swap(from);vector<int>().swap(to);vector<long long>d(count,-1);d[comp[S]]=money[comp[S]];vector<int>q;q.reserve(count);for(int i=0;i<count;i++)if(!degree[i])q.push_back(i);long long ans=0;for(size_t i=0;i<q.size();i++){int u=q[i];if(pub[u]&&d[u]>=0)ans=max(ans,d[u]);for(int at=head[u];at<head[u+1];at++){int v=dag[at];if(d[u]>=0)d[v]=max(d[v],d[u]+money[v]);if(--degree[v]==0)q.push_back(v);}}cout<<ans<<'\n';}
    
    • 1

    信息

    ID
    1577
    时间
    1000ms
    内存
    128MiB
    难度
    提高
    标签
    递交数
    1
    已通过
    1
    上传者