题解 P3387 【【模板】缩点】(待完善)

pantw

2018-01-25 22:55:32

Solution

QAQ还是先丢着吧emmm 回头再来写题解。 ~~好久没有写操作符不空格的代码辣~~ ---- ```cpp #include <cstdio> #define maxn 10010 #define maxm 200010 int p[maxn],head[maxn],nhead[maxn],nxt[maxm],to[maxm],ec; int stk[maxn],top,ins[maxn]; int dfn[maxn],low[maxn],ds; int scc[maxn],sccno; int in[maxn],res[maxn],ress,dp[maxn],val[maxn]; inline int min(int a,int b){ return a<b?a:b; } inline int max(int a,int b){ return a>b?a:b; } inline void add(int*h,int u, int v){ nxt[++ec]=h[u],h[u]=ec,to[ec]=v; } int dfs(int x){ if(dfn[x])return low[x]; dfn[x]=low[x]=++ds; ins[x]=stk[++top]=x; for(int e=head[x];e;e=nxt[e]){ if(!dfn[to[e]])low[x]=min(low[x],dfs(to[e])); else if(ins[to[e]])low[x]=min(low[x],dfn[to[e]]); } if(dfn[x]==low[x]){ sccno++; while(stk[top+1]!=x)scc[stk[top]]=sccno,ins[stk[top--]]=0; } return low[x]; } void topo(int x){ res[++ress]=x; for(int e=nhead[x];e;e=nxt[e])if(!--in[to[e]])topo(to[e]); } int main(){ int n,m,u,v,ans=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i)scanf("%d",p+i); for(int i=1;i<=m;++i)scanf("%d%d",&u,&v),add(head,u,v); for(int i=1;i<=n;++i)if(!dfn[i])dfs(i); for(int i=1;i<=n;++i)for(int e=head[i];e;e=nxt[e])if(scc[i]!=scc[to[e]])add(nhead,scc[i],scc[to[e]]),in[scc[to[e]]]++; for(int i=1;val[scc[i]]+=p[i],i<=sccno;++i)if(!in[i])topo(i); for(int i=ress,x=res[i];i;ans=max(ans,dp[x]+=val[x]),x=res[--i])for(int e=nhead[x];e;e=nxt[e])dp[x]=max(dp[x],dp[to[e]]); printf("%d\n", ans); } ```