LOJ10096掠夺计划

题目传送门:https://loj.ac/problem/10096

-------------------------------------------------------------------------------------------------------

强联通分量内的ATM只要有一个可以抢到就都可以抢到的,所以要缩点。

当然,要统计整个分量内可以抢到的钱的和。

分量内只要有一个路口有酒吧,那么这个分量就可以作为结束点进行庆祝,所以要统计每个分量内是否有酒吧。

然后在缩点后的有向无环图上进行拓扑排序,然后进行DP,求出到每个分量可以抢到的最大钱数。

最后把所有抢到钱的分量中,求出有酒吧且最大的就是答案。

-------------------------------------------------------------------------------------------------------

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=5e5+10;
 4 const int maxm=5e5+10;
 5 int n,m;
 6 struct edge
 7 {
 8     int u,v,nxt;
 9 }e[maxm],ee[maxm];
10 int head[maxn],js,headd[maxn],jss;
11 void addage(edge e[],int head[],int &js,int u,int v)
12 {
13     e[++js].u=u;e[js].v=v;
14     e[js].nxt=head[u];head[u]=js;
15 }
16 int dfn[maxn],low[maxn],st[maxn],top,cnt,lt[maxn],lts;
17 void tarjan(int u)
18 {
19     dfn[u]=low[u]=++cnt;
20     st[++top]=u;
21     for(int i=head[u];i;i=e[i].nxt)
22     {
23         int v=e[i].v;
24         if(!dfn[v])
25         {
26             tarjan(v);
27             low[u]=min(low[u],low[v]);
28         }
29         else if(!lt[v])
30             low[u]=min(low[u],dfn[v]);
31     }
32     if(dfn[u]==low[u])
33     {
34         lt[u]=++lts;
35         while(st[top]!=u)lt[st[top--]]=lts;
36         --top;
37     }
38 }
39 int money[maxn],moneys[maxn],s,p;
40 bool isp[maxn],isps[maxn];
41 int f[maxn];
42 bool inq[maxn];
43 queue<int>q;
44 void dfs(int x)
45 {
46     q.push(x);
47     while(!q.empty())
48     {
49         int u=q.front();q.pop();inq[u]=0;
50         for(int i=headd[u];i;i=ee[i].nxt)
51         {
52             int v=ee[i].v;
53             if(f[u]+moneys[v]>f[v])
54             {
55                 f[v]=f[u]+moneys[v];
56                 if(!inq[v])
57                 {
58                     q.push(v);
59                     inq[v]=1;
60                 }
61             }
62         }
63     }
64 }
65 int main()
66 {
67     scanf("%d%d",&n,&m);
68     for(int u,v,i=0;i<m;++i)
69     {
70         scanf("%d%d",&u,&v);
71         addage(e,head,js,u,v);
72     }
73     for(int i=1;i<=n;++i)scanf("%d",money+i);
74     scanf("%d%d",&s,&p);
75     for(int x,i=0;i<p;++i)
76     {
77         scanf("%d",&x);
78         isp[x]=1;
79     }
80     for(int i=1;i<=n;++i)
81         if(!dfn[i])tarjan(i);
82     for(int i=1;i<=n;++i)
83     {
84         moneys[lt[i]]+=money[i];
85         if(isp[i])isps[lt[i]]=1;
86     }
87     for(int u=1;u<=n;++u)
88         for(int i=head[u];i;i=e[i].nxt)
89         {
90             int v=e[i].v;
91             if(lt[u]!=lt[v])addage(ee,headd,jss,lt[u],lt[v]);
92         }
93     f[lt[s]]=moneys[lt[s]];
94     dfs(lt[s]);
95     int ans=0;
96     for(int i=1;i<=lts;++i)if(isps[i])ans=max(ans,f[i]);
97     cout<<ans;
98     return 0; 
99 }
View Code
原文地址:https://www.cnblogs.com/gryzy/p/10765152.html