[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 }