[APIO2009]抢掠计划

tarjan 缩点,跑个最长路。

#include <vector>
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int N=500005;
vector<int>G[N],V[N];
int n,m,ecnt,head[N],val[N],S,p,tim,dfn[N],low[N],stk[N],top,sum[N],col[N],cnt,dis[N];
bool inq[N],vis[N];
struct Edge{int to,nxt,val;}e[N<<1];
void add(int bg,int ed) {e[++ecnt].nxt=head[bg];e[ecnt].to=ed;head[bg]=ecnt;}
void tarjan(int x) {
  low[x]=dfn[x]=++tim;inq[x]=1;stk[++top]=x;
  for(int i=head[x];i;i=e[i].nxt) {
    int v=e[i].to;
    if(!dfn[v]) {
      tarjan(v);low[x]=min(low[v],low[x]);
    }
    else if(inq[v]) low[x]=min(low[x],dfn[v]);
  }
  if(dfn[x]==low[x]) {
    ++cnt;
    int k;
    do{
      k=stk[top--];
      col[k]=cnt;
      inq[k]=0;
      sum[cnt]+=val[k];
    }while(k!=x);
  }
}
void spfa() {
  memset(dis,0x3f,sizeof dis);
  queue<int>q;
  q.push(col[0]);
  dis[col[0]]=0;vis[col[0]]=1;
  while(!q.empty()){
    int u=q.front();q.pop();vis[u]=0;
    for(int i=0;i<G[u].size();i++){
      int v=G[u][i];
      if(dis[v]>dis[u]+V[u][i]) {
        dis[v]=dis[u]+V[u][i];
        if(!vis[v]) vis[v]=1,q.push(v);
      }
    }
  }
}
int main() {
  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%d",&S,&p);
  int id[N];
  for(int i=1;i<=p;i++) scanf("%d",&id[i]);
  add(0,S);
  for(int i=0;i<=n;i++) if(!dfn[i]) tarjan(i);
  for(int i=0;i<=n;i++) {
    for(int j=head[i];j;j=e[j].nxt) {
      int v=e[j].to;
      if(col[v]!=col[i]) G[col[i]].push_back(col[v]),V[col[i]].push_back(-sum[col[v]]);
    }
  }
  spfa();
  int ans=0;
  for(int i=1,b;i<=p;i++) ans=max(ans,-dis[col[id[i]]]);
  cout<<ans;
}

猜你喜欢

转载自www.cnblogs.com/sdfzhsz/p/9362802.html