题目描述

[Apio2009]Atm

输入

第一行包含两个整数N、M。N表示路口的个数,M表示道路条数。接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号。接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数。接下来一行包含两个整数S、P,S表示市中心的编号,也就是出发的路口。P表示酒吧数目。接下来的一行中有P个整数,表示P个有酒吧的路口的编号

输出

输出一个整数,表示Banditji从市中心开始到某个酒吧结束所能抢劫的最多的现金总数。

样例输入

6 7 1 2 2 3 3 5 2 4 4 1 2 6 6 5 10 12 8 16 1 5 1 4 4 3 5 6

样例输出

47

提示

50%的输入保证N, M<=3000。所有的输入保证N, M<=500000。每个ATM机中可取的钱数为一个非负整数且不超过4000。输入数据保证你可以从市中心沿着Siruseri的单向的道路到达其中的至少一个酒吧。

抢劫是不对的,要弘扬社会主义核心价值观。

缩点裸题

Tarjan求联通分量缩点,再spfa

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 struct Messi
  7 {
  8     int next,to;
  9 }edge[500001],edge2[500001];
 10 int head[500001],num,low[500001],dfn[500001],dfscnt,stack[500001],inStack[500001];
 11 int point[500001],n,m,scnt,top,sccno[500001],ans,num2,head2[500001],w[500001],dist[500001],q[5000001];
 12 bool b2[500001];
 13 bool b[500001];
 14 void add(int u,int v)
 15 {
 16     num++;
 17     edge[num].next=head[u];
 18      edge[num].to=v;
 19      head[u]=num;
 20 }
 21 void add2(int u,int v)
 22 {
 23     num2++;
 24     edge2[num2].next=head2[u];
 25      edge2[num2].to=v;
 26      head2[u]=num2;
 27 }
 28 void dfs(int u)
 29 {int i,j;
 30     low[u]=dfn[u]=++dfscnt;
 31     stack[++top]=u;
 32      inStack[u]=1;
 33      for (i=head[u];i;i=edge[i].next)
 34      {
 35         int v=edge[i].to;
 36          if (dfn[v]==0)
 37          {
 38             dfs(v);
 39             low[u]=min(low[u],low[v]);
 40          }else if (inStack[v]) low[u]=min(low[u],dfn[v]);
 41      }
 42      if (dfn[u]==low[u])
 43      {
 44         ++scnt;
 45         while (top&&stack[top+1]!=u)
 46         {
 47             sccno[stack[top]]=scnt;
 48             inStack[stack[top--]]=0;
 49         }
 50      }
 51 }
 52 int main()
 53 {int i,j,u,v,s,p,k,h,t;
 54 //freopen("2.in","r",stdin);
 55 //freopen("2.out","w",stdout);
 56     cin>>n>>m;
 57      for (i=1;i<=m;i++)
 58       {
 59         scanf("%d%d",&u,&v);
 60         add(u,v);
 61       }
 62        for (i=1;i<=n;i++)
 63        scanf("%d",&w[i]);
 64      cin>>s>>p;
 65       for (i=1;i<=p;i++)
 66       {
 67         scanf("%d",&k);
 68          b[k]=1;
 69       }
 70       for (i=1;i<=n;i++)
 71        if (dfn[i]==0) dfs(i);
 72        for (i=1;i<=n;i++)
 73        {
 74          int u=sccno[i];
 75             point[u]+=w[i];
 76             if (b[i]) b2[u]=1;
 77           for (j=head[i];j;j=edge[j].next)
 78            {
 79             int v=sccno[edge[j].to];
 80             if (u!=v) add2(u,v);
 81            }
 82        }
 83       q[1]=sccno[s];
 84       dist[sccno[s]]=point[sccno[s]];
 85        h=0;t=1;
 86        while (h<t)
 87        {
 88         h++;
 89         u=q[h];
 90          for (i=head2[u];i;i=edge2[i].next)
 91          {
 92             v=edge2[i].to;
 93              if (dist[u]+point[v]>dist[v])
 94               {
 95                   dist[v]=dist[u]+point[v];
 96               t++;
 97               q[t]=v;
 98              }
 99          }
100        }  
101     for (i=1;i<=scnt;i++)
102      if (b2[i])
103       ans=max(ans,dist[i]);
104       cout<<ans;
105 }

 

相关文章: