P3387 【模板】缩点

题面

https://www.luogu.org/problem/P3387

题解

#include<iostream>
#include<vector>
#include<cstdio>
#include<stack>
#include<map>
#include<cstring>
const int inf=987654321;
using namespace std;
int n,m,a[10050],dfn[10050],low[10500],cloct,bel[10500],ru[10500],f[10500];
int u[100500],v[100500];
bool ins[10050];
vector<int> to[10050],about[10050];
map<int,bool> abo[10050];
stack<int> s;

void tarjan(int x){
  low[x]=dfn[x]=++cloct;
  s.push(x);
  ins[x]=true;
  int i,l=to[x].size(),t;
  for (i=0;i<l;i++) {
    if (ins[to[x][i]]) low[x]=min(low[x],dfn[to[x][i]]);
    else 
      if (dfn[to[x][i]]==0) {
        tarjan(to[x][i]);
        low[x]=min(low[x],low[to[x][i]]);
      }
  }
  if (low[x]==dfn[x]) {
    do {
      t=s.top();
      bel[t]=x;
      ins[t]=false;
      s.pop();
      if (t==x) break;
    } while (1);
  }
  return;
}

void dp(int x){
  if (f[x]>0) return;
  int i,l=about[x].size(),maxd=0;
  f[x]=a[x];
  for (i=0;i<l;i++) {
    dp(about[x][i]);
    if (f[about[x][i]]>maxd) maxd=f[about[x][i]];
  }
  f[x]+=maxd;
}

int main(){
  int i,j,uu,vv;
  scanf("%d %d",&n,&m);
  for (i=1;i<=n;i++) scanf("%d",&a[i]);
  for (i=1;i<=m;i++) {
    scanf("%d %d",&u[i],&v[i]);
    to[u[i]].push_back(v[i]);
  }
  cloct=0;
  for (i=1;i<=n;i++) if (!dfn[i]) tarjan(i);
  for (i=1;i<=n;i++) if (bel[i]!=i) a[bel[i]]+=a[i];
  for (i=1;i<=m;i++) {
    uu=bel[u[i]]; vv=bel[v[i]];
    if (uu!=vv && !abo[uu].count(vv)) {
      abo[uu][vv]=true;
      ru[vv]++;
      about[uu].push_back(vv);
    }
  }
  memset(f,-0x3f,sizeof(f));
  int ans=-inf;
  for (i=1;i<=n;i++) if (!ru[bel[i]] && f[bel[i]]<-inf) {
    dp(bel[i]);
    if (f[bel[i]]>ans) ans=f[bel[i]];
  }
  cout<<ans<<endl;
}

 

posted @ 2019-08-29 00:35  HellPix  阅读(164)  评论(0编辑  收藏  举报