做题记录整理图论5 P3627 [APIO2009] 抢掠计划(2022/10/11)
先tarjan缩点,然后全部变成负边权,最后dij求最短路在*-1就得了(然而调了一下午)
#include<bits/stdc++.h>
#define for1(i,a,b) for(int i = a;i<=b;i++)
#define ll long long
#define mp(a,b) make_pair(a,b)
using namespace std;
const int inf = 1e9;
struct node{
int nex;
int to;
}e[500005];
int a[500005],id[500005],sum[500005],zhan[500005],top,kg,k;
int dis[500005],hd[500005],cnt;
vector <int> h[500005],hh[500005];
int p[500005],dfn[500005],low[500005],jl;
bool ins[500005],vis[500005];
int n,m,u,v,S,P,ans;
queue <int> q;
void ru(int x,int y)
{
e[++cnt].to = y;
e[cnt].nex = hd[x];
hd[x]=cnt;
}
void tarjan (int x)
{
dfn[x]=low[x]=++jl;
zhan[++top]=x;
ins[x]=1;
for(int i = hd[x];i;i=e[i].nex)
{
int v=e[i].to;
if (!dfn[v])
tarjan (v),
low[x] = min(low[x], low[v]);
else if (ins[v])
low[x] = min(low[x], dfn[v]);
}
if(dfn[x] == low[x])
{
++kg;
do {
k = zhan[top--];
ins[k] = 0;
id[k] = kg;
sum[kg] += a[k];
} while(x!=k);
}
}
int main()
{
cin>>n>>m;
for1(i,1,m)
{
scanf("%d%d",&u,&v);
ru(u,v);
}
for1(i,1,n) scanf("%d",&a[i]);
for1(i,1,n)
if (!dfn[i])
tarjan (i);
cin>>S>>P;
for1(i,1,P)
scanf("%d",&p[i]);
for1(i,1,n)
for(int j = hd[i]; j; j = e[j].nex)
if(id[i] != id[e[j].to])
h[id[i]+kg].push_back(id[e[j].to]),hh[id[i]+kg].push_back(0);
for1(i,1,kg)
h[i].push_back(i+kg),hh[i].push_back(sum[i]);
memset(dis,-inf,sizeof(dis));
vis[id[S]] =1,dis[id[S]] = 0;
q.push(id[S]);
while(!q.empty ())
{
int x = q.front();
q.pop ();
vis[x] = 0;
for(int i = 0;i<h[x].size();i++)
{
int v=h[x][i],w=hh[x][i];
if(dis[v] < dis[x] + w)
{
dis[v] = dis[x]+w;
if(!vis[v])
{
q.push(v);
vis[v] = 1;
}
}
}
}
for1(i,1,P)
ans=max(ans,dis[id[p[i]]+kg]);
printf ("%d\n",ans);
}

浙公网安备 33010602011771号