分析
水题
tarjan缩完点在拓扑序上随便DP,并查集维护连通块
#include <iostream> #include <cstdio> #include <memory.h> #include <queue> #include <algorithm> using namespace std; const int N=1e5+10; struct Edge { int u,v,nx; }g[10*N]; int cnt,list[N],val[N],w[N],f[N],deg[N],fa[N],ans[N]; int low[N],dfn[N],tme; int stk[N],top,bel[N],id,stack[N],tp,icnt; bool instk[N],vis[N]; int n,m,k; int Get_F(int x) {return fa[x]==x?x:fa[x]=Get_F(fa[x]);} void Add(int u,int v) {g[++cnt]=(Edge){u,v,list[u]};list[u]=cnt;} void Tarjan(int v0) { stack[++tp]=v0; while (tp) { int u=stack[tp],i; if (!dfn[u]) low[u]=dfn[u]=++tme,stk[++top]=u,instk[u]=1; for (i=list[u];i;i=g[i].nx) if (!dfn[g[i].v]) break; else if (instk[g[i].v]) low[u]=min(low[u],dfn[g[i].v]); if (!i&&tp>1) low[stack[tp-1]]=min(low[stack[tp-1]],low[u]); if (!i) { if (dfn[u]==low[u]) { ++id; do { bel[stk[top]]=id;instk[stk[top]]=0;w[id]+=val[stk[top]]; } while (stk[top--]!=u); } tp--; } else stack[++tp]=g[i].v; } } bool CMP(int a,int b) { return a>b; } void ToppoSort() { queue<int> q; while (!q.empty()) q.pop(); for (int i=1;i<=id;i++) if (!deg[i]) q.push(i); while (!q.empty()) { int u=q.front();q.pop();f[u]+=w[u]; for (int i=list[u];i;i=g[i].nx) { f[g[i].v]=max(f[g[i].v],f[u]);deg[g[i].v]--; if (!deg[g[i].v]) q.push(g[i].v); } } for (int i=1;i<=id;i++) ans[Get_F(i)]=max(ans[Get_F(i)],f[i]),icnt+=!vis[Get_F(i)],vis[Get_F(i)]=1; sort(ans+1,ans+n+1,CMP); int lans=0; for (int i=1;i<=min(k+1,icnt);i++) lans+=ans[i]; printf("%d ",lans); } int main() { freopen("azeroth.in","r",stdin);freopen("azeroth.out","w",stdout); scanf("%d%d",&n,&m); for (int i=1,u,v;i<=m;i++) scanf("%d%d",&u,&v),Add(u,v); for (int i=1;i<=n;i++) scanf("%d",&val[i]); scanf("%d",&k); for (int i=1;i<=n;i++) if (!dfn[i]) Tarjan(i); cnt=0;memset(list,0,sizeof list); for (int i=1;i<=id;i++) fa[i]=i; for (int i=1;i<=m;i++) if (bel[g[i].u]!=bel[g[i].v]) deg[bel[g[i].v]]++,fa[Get_F(bel[g[i].u])]=Get_F(bel[g[i].v]),Add(bel[g[i].u],bel[g[i].v]); ToppoSort(); }