P3627 [APIO2009] 抢掠计划(atm) 题解
分析
显然我们要处理最多的马内的路径,就要跑最长路,那么就可以用spfa跑
但是有环,spfa不能用spfa会似掉
好办,跑一遍tarjan干掉环,spfa就又活了
停下的酒馆也好处理,直接遍历找求max
数组功能介绍
const int maxn=1000010;
int n,m,s,p;
int dis[maxn];// 跑spfa用
int h[maxn],to[maxn],nxt[maxn],w[maxn],tot,cnt,num;// 前向星用,w存一开始的点权
int h1[maxn],to1[maxn],nxt1[maxn],tot1,w1[maxn],w2[maxn];// 缩点后的存储
int zhan[maxn],top,in_zhan[maxn];//栈及元素是否在栈判断
int dfn[maxn],low[maxn],c[maxn];// tarjan用
bool v[maxn],bar[maxn],bar1[maxn];// v是跑spfa用的,bar就是原酒馆,bar1是缩点后的
int ans;
vector<int> scc[maxn];// tarjan的
Code
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000010;
int n,m,s,p;
int dis[maxn];
int h[maxn],to[maxn],nxt[maxn],w[maxn],tot,cnt,num;
int h1[maxn],to1[maxn],nxt1[maxn],tot1,w1[maxn],w2[maxn];
int zhan[maxn],top,in_zhan[maxn];
int dfn[maxn],low[maxn],c[maxn];
bool v[maxn],bar[maxn],bar1[maxn];
int ans;
vector<int> scc[maxn];
void add(int x,int y)
{
tot++;
to[tot]=y;
nxt[tot]=h[x];
h[x]=tot;
}
void add1(int x,int y,int z)
{
tot1++;
to1[tot1]=y;
nxt1[tot1]=h1[x];
w2[tot1]=z;
h1[x]=tot1;
}
void tarjan(int x)
{
int y=0;
num++;
dfn[x]=low[x]=num;
zhan[++top]=x;
in_zhan[x]=true;
for (int i=h[x];i;i=nxt[i])
{
y=to[i];
if (!dfn[y])
{
tarjan(y);
low[x]=min(low[x],low[y]);
}
else if (in_zhan[y])
{
low[x]=min(low[x],dfn[y]);
}
}
if (dfn[x] == low[x])
{
cnt++;
do
{
y=zhan[top];
top--;
in_zhan[y]=false;
c[y]=cnt;
scc[cnt].push_back(y);
w1[cnt]+=w[y];
if (bar[y]) bar1[cnt]=true;
} while (x!=y);
}
}
void spfa_long(int x)
{
queue<int> q;
memset(dis,0,sizeof(dis));// 注意初始化
dis[x]=w1[x];
q.push(x);
v[x] = true;
while (q.size())
{
x=q.front();
q.pop();
v[x]=false;
for (int i=h1[x];i;i=nxt1[i])
{
int y=to1[i];
if (dis[y]<dis[x]+w2[i])// 注意
{
dis[y]=dis[x]+w2[i];
if (!v[y]) q.push(y);
}
}
}
}
int main()
{
cin >> n >> m;
int x,y;
for (int i=1;i<=m;i++)
{
cin >> x >> y;
add(x,y);
}
for (int i=1;i<=n;i++) cin >> w[i];
cin >> s >> p;
for (int i=1;i<=p;i++)
{
cin >> x;
bar[x]=true;
}
for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i);
for (int i=1;i<=n;i++)
{
for (int j=h[i];j;j=nxt[j])
{
int y=to[j];
if (c[i] == c[y]) continue;
add1(c[i],c[y],w1[c[y]]);
}
}
spfa_long(c[s]);
for (int i=1;i<=cnt;i++)
{
if (bar1[i]) ans = max(ans,dis[i]);
}
cout << ans << endl;
return 0;
}

浙公网安备 33010602011771号