APIO2009 洛谷P3678 劫掠计划

题目传送门:https://www.luogu.org/problemnew/show/P3627

题解:tarjan强连通分量缩点+bfsspfa

代码如下:

 1 #include<cstdio>
 2 #include<iostream>
 3 #define MN 1000010
 4 using namespace std;
 5 int n,m,w[MN],bar[MN],S,P,ans,hd[MN],cnt,sz[MN],CN,dis[MN],s[MN];
 6 int dye[MN],q[MN],top,dfn[MN],low[MN],dfs_ct,re_ct,re_hd[MN];
 7 bool vis[MN];
 8 struct node{int to,nex,d;}e[MN],re_e[MN];
 9 void add(int x,int y){e[++cnt].to=y;e[cnt].nex=hd[x];hd[x]=cnt;}
10 void tarjan(int x){
11     vis[q[++top]=x]=true;
12     dfn[x]=low[x]=++dfs_ct;
13     for(int i=hd[x];i;i=e[i].nex){
14         if(!dfn[e[i].to]){
15             tarjan(e[i].to);
16             low[x]=min(low[x],low[e[i].to]);
17         }
18         else if(vis[e[i].to])
19             low[x]=min(low[x],dfn[e[i].to]);
20     }
21     if(dfn[x]==low[x]){
22         vis[x]=false;
23         sz[dye[x]=++CN]+=w[x];
24         while(x!=q[top]){
25             sz[dye[q[top]]=CN]+=w[q[top]];
26             vis[q[top--]]=false;
27         }
28         --top;
29     }
30 }
31 void rebuild(){
32     for(int i=1;i<=n;++i)
33         for(int j=hd[i];j;j=e[j].nex)
34             if(dye[i]!=dye[e[j].to]&&dye[i]&&dye[e[j].to]){
35                 re_e[++re_ct].to=dye[e[j].to];
36                 re_e[re_ct].d=sz[dye[e[j].to]];
37                 re_e[re_ct].nex=re_hd[dye[i]];
38                 re_hd[dye[i]]=re_ct;
39             }
40 }
41 bool spfa(int u){
42     int head=1,tail=1; s[1]=u;
43     while(head<=tail){
44         u=s[head++];
45         for(int i=re_hd[u];i;i=re_e[i].nex){
46             int v=re_e[i].to;
47             if(re_e[i].d+dis[u]>dis[v]){
48                 dis[v]=re_e[i].d+dis[u];
49                 s[++tail]=v;
50             }
51         }
52     }
53 }
54 int main()
55 {
56     scanf("%d%d",&n,&m);
57     for(int i=1;i<=m;i++){
58         int x,y; scanf("%d%d",&x,&y);
59         add(x,y);
60     }
61     for(int i=1;i<=n;i++) scanf("%d",&w[i]);
62     scanf("%d%d",&S,&P);
63     for(int i=1;i<=P;i++){
64         int x; scanf("%d",&x);
65         bar[x]=true;
66     }
67     for(int i=1;i<=n;i++)if(!dye[i]) tarjan(i);
68     rebuild();
69     dis[dye[S]]=sz[dye[S]];
70     spfa(dye[S]);
71     for(int i=1;i<=n;i++)
72         if(bar[i])if(dis[dye[i]]>ans) ans=dis[dye[i]];
73     printf("%d",ans);
74     return 0;
75 }
原文地址:https://www.cnblogs.com/Beginner-/p/8795716.html