这题一看就是缩点,但是缩完点怎么办呢?首先我们把所有的包含酒吧的缩点找出来,打上标记,然后建立一张新图,
每个缩点上的点权就是他所包含的所有点的点权和。但是建图的时候要注意,每一对缩点之间可能有多条边,所以我们可以先把重边去除一下,在建立新图,具体操作如下:
1 for(int i=1;i<=n;i++)
2 {
3 if(vis[i]==0) continue;
4 for(int j=last[i];j;j=g[j].next)
5 {
6 int v=g[j].to;
7 if(g[i].co!=g[v].co&&vis[v]==1)
8 {
9 e[++cnt].a=g[i].co;
10 e[cnt].b=g[v].co;
11 }
12 }
13 }
14 sort(e+1,e+cnt+1,cmp);
15 for(int i=1;i<=cnt;i++)
16 {
17 if(e[i].a!=e[i-1].a||e[i].b!=e[i-1].b)
18 {
19 add1(e[i].a,e[i].b);
20 }
21 }
具体思路就是先枚举所有点和所有边,如果两个点不属于同一个强联通分量,那么就用e来把边存一下,然后对e进行排序
,去重,再建图。
建完图之后就好办了,可以跑spfa单源最长路,也可以dp,因为最后一定会终止在酒吧,所以就取所有打过标记的节点的最大值就好了。
最后附上代码:
1 #include<iostream>
2 #include<cmath>
3 #include<cstdio>
4 #include<string>
5 #include<cstring>
6 #include<algorithm>
7 #define maxn 500005
8 using namespace std;
9 struct edge
10 {
11 int next;
12 int to;
13 int co;
14 }g[maxn];
15
16 struct edge1
17 {
18 int next;
19 int to;
20 }g1[maxn];
21 struct edhe
22 {
23 int a,b;
24 }e[maxn];
25
26
27 inline int read()
28 {
29 char c=getchar();
30 int res=0,x=1;
31 while(c<'0'||c>'9')
32 {
33 if(c=='-')
34 x=-1;
35 c=getchar();
36 }
37 while(c>='0'&&c<='9')
38 {
39 res=res*10+(c-'0');
40 c=getchar();
41 }
42 return x*res;
43 }
44
45 int n,m,aa,bb,num,s,p,tot,top,col,num1,ans,ae,cnt;
46 int last[maxn],a[maxn],b[maxn],dfn[maxn],st[maxn],low[maxn];
47 int shu[maxn],d[maxn],last1[maxn],sum[maxn],vis[maxn];
48
49 inline void add(int from,int to)
50 {
51 g[++num].next=last[from];
52 g[num].to=to;
53 last[from]=num;
54 }
55
56 inline void add1(int from,int to)
57 {
58 g1[++num1].next=last1[from];
59 g1[num1].to=to;
60 last1[from]=num1;
61 }
62
63 inline void tarjan(int u)
64 {
65 low[u]=dfn[u]=++tot;
66 st[++top]=u;
67 for(int i=last[u];i;i=g[i].next)
68 {
69 int v=g[i].to;
70 if(!dfn[v])
71 {
72 tarjan(v);
73 if(low[v]<low[u])
74 low[u]=low[v];
75 }
76 else if(!g[v].co)
77 {
78 if(dfn[v]<low[u])
79 low[u]=dfn[v];
80 }
81 }
82 if(low[u]==dfn[u])
83 {
84 g[u].co=++col;
85 while(st[top]!=u)
86 {
87 g[st[top]].co=col;
88 top--;
89 }
90 top--;
91 }
92 }
93
94 void dfs(int x)
95 {
96 for(int i=last1[x];i;i=g1[i].next)
97 {
98 int v=g1[i].to;
99 if(sum[x]+shu[v]>sum[v])
100 {
101 sum[v]=sum[x]+shu[v];
102 dfs(v);
103 }
104 }
105 }
106
107 bool cmp(edhe a,edhe b)
108 {
109 if(a.a==b.a)
110 {
111 return a.b<b.b;
112 }
113 else return a.a<b.a;
114 }
115
116 int main()
117 {
118 n=read();
119 m=read();
120 for(int i=1;i<=m;i++)
121 {
122 aa=read();bb=read();
123 add(aa,bb);
124 }
125 for(int i=1;i<=n;i++)
126 {
127 a[i]=read();
128 }
129 s=read();p=read();
130 for(int i=1;i<=p;i++)
131 {
132 aa=read();
133 b[aa]=1;
134 }
135 for(int i=1;i<=n;i++)
136 {
137 if(!dfn[i])
138 tarjan(i);
139 }
140 for(int i=1;i<=n;i++)
141 {
142 shu[g[i].co]+=a[i];
143 if(b[i]==1)
144 {
145 d[g[i].co]=1;
146 }
147 }
148 for(int i=1;i<=n;i++)
149 {
150 if(vis[i]==0) continue;
151 for(int j=last[i];j;j=g[j].next)
152 {
153 int v=g[j].to;
154 if(g[i].co!=g[v].co)
155 {
156 e[++cnt].a=g[i].co;
157 e[cnt].b=g[v].co;
158 }
159 }
160 }
161 sort(e+1,e+cnt+1,cmp);
162 for(int i=1;i<=cnt;i++)
163 {
164 if(e[i].a!=e[i-1].a||e[i].b!=e[i-1].b)
165 {
166 add1(e[i].a,e[i].b);
167 }
168 }
169 sum[g[s].co]=shu[g[s].co];
170 dfs(g[s].co);
171 for(int i=1;i<=col;i++)
172 {
173 if(d[i]==1)
174 {
175 if(ans<sum[i])
176 ans=sum[i];
177 }
178 }
179 printf("%d",ans);
180 return 0;
181 }