您的位置:首页 > 其它

[BZOJ1179] [Apio2009]Atm(强连通)

2018-02-13 10:56 405 查看
题意传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1179

由于一个环上的点一定可以全部拿到,所以可以考虑强连通缩点,缩点之后用连通块建新图,将有酒吧的连通块连到ed,跑一边最长路即可。

(初始化的位置一定要放对啊啊啊啊!!!

code:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=500010;
struct node
{
int x,y,c,next;
}a[maxn*2],b[maxn*2];
int len1,last1[maxn];
int len2,last2[maxn];
int n,m;
void ins1(int x,int y)
{
len1++; a[len1].x=x;a[len1].y=y;
a[len1].next=last1[x]; last1[x]=len1;
}
void ins2(int x,int y,int c)
{
len2++; b[len2].x=x;b[len2].y=y;b[len2].c=c;
b[len2].next=last2[x]; last2[x]=len2;
}
int low[maxn],dfn[maxn],id;
int sta[maxn],top; bool insta[maxn];
int bl[maxn],scc;
int w[maxn],sum[maxn];
void dfs(int x)
{
dfn[x]=low[x]=++id;
sta[++top]=x; insta[x]=true;
for(int k=last1[x];k;k=a[k].next)
{
int y=a[k].y;
if(dfn[y]==-1)
{
dfs(y);
low[x]=min(low[x],low[y]);
}
else
{
if(insta[y]) low[x]=min(low[x],dfn[y]);
}
}
if(low[x]==dfn[x])
{
int i; scc++;
do{
i=sta[top--];
bl[i]=scc;
insta[i]=false;
sum[scc]+=w[i];
}while(i!=x);
}
}
int st,ed,stt;
bool ved[maxn];
void rebuild()
{
st=bl[stt];
for(int i=1;i<=len1;i++)
{
int x=a[i].x,y=a[i].y;
if(bl[x]!=bl[y])
ins2(bl[x],bl[y],sum[bl[x]]);
}
for(int i=1;i<=n;i++)
{
if(ved[i]==true)
{
ins2(bl[i],ed,sum[bl[i]]);
}
}
}
int d[maxn];
int list[maxn*2],head,tail;
bool vs[maxn];
void spfa()
{
memset(d,-1,sizeof(d)); d[st]=0;
memset(vs,false,sizeof(vs)); vs[st]=true;
head=1,tail=2; list[head]=st;
while(head!=tail)
{
int x=list[head];
for(int k=last2[x];k;k=b[k].next)
{
int y=b[k].y;
if(d[y]<d[x]+b[k].c)
{
d[y]=d[x]+b[k].c;
if(vs[y]==false)
{
vs[y]=true;
list[tail++]=y;
}
}
}
head++; vs[x]=false;
}
}
void init()
{
id=top=scc=len1=len2=0;
memset(dfn,-1,sizeof(dfn));
memset(low,0,sizeof(low));
memset(sta,0,sizeof(sta));
memset(bl,0,sizeof(bl));
memset(sum,0,sizeof(sum));
memset(last1,0,sizeof(last1));
memset(last2,0,sizeof(last2));
}
int main()
{
init();
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
ins1(u,v);
}
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
int tt; scanf("%d%d",&stt,&tt);
for(int ti=1;ti<=tt;ti++)
{
int x;scanf("%d",&x);
ved[x]=true;
}

for(int i=1;i<=n;i++)
if(dfn[i]==-1)
dfs(i);
ed=scc+1;

rebuild();
spfa();

printf("%d\n",d[ed]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: