您的位置:首页 > 其它

[bzoj 1179--Apio2009]Atm

2018-02-12 16:44 281 查看
Siruseri 城中的道路都是单向的。不同的道路由路口连接。按照法律的规定, 在每个路口都设立了一个 Siruseri 银行的 ATM取款机。令人奇怪的是,Siruseri 的酒吧也都设在路口,虽然并不是每个路口都设有酒吧。 Banditji 计划实施 Siruseri有史以来最惊天动地的 ATM 抢劫。他将从市中心 出发,沿着单向道路行驶,抢劫所有他途径的 ATM 机,最终他将在一个酒吧庆 祝他的胜利。

使用高超的黑客技术,他获知了每个 ATM 机中可以掠取的现金数额。他希望你帮助他计算从市中心出发最后到达某个酒吧时最多能抢劫的现金总数。他可 以经过同一路口或道路任意多次。但只要他抢劫过某个 ATM 机后,该ATM 机 里面就不会再有钱了。 例如,假设该城中有 6 个路口,道路的连接情况如下图所示:



市中心在路口 1,由一个入口符号→来标识,那些有酒吧的路口用双圈来表 示。每个 ATM机中可取的钱数标在了路口的上方。在这个例子中,Banditji 能抢 劫的现金总数为 47,实施的抢劫路线是:1-2-4-1-2-3-5。

这道题非常套路地先强联通缩点一下,统计出一个联通分块的总价值。然后给各个联通分块连边, 边权为边中出发联通块的总价值。然后找出st,并将有酒馆的联通块与ed相连,边权也为出发联通块的总价值。之后就解决了这道水题。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
using namespace std;
struct node
{
int x,y,next;
}a[510000];int len,last[510000];
void ins(int x,int y)
{
len++;
a[len].x=x;a[len].y=y;
a[len].next=last[x];last[x]=len;
}
struct bian
{
int x,y,c,next;
}tr[510000];int trlen,trlast[510000];
void trins(int x,int y,int c)
{
trlen++;
tr[trlen].x=x;tr[trlen].y=y;tr[trlen].c=c;
tr[trlen].next=trlast[x];trlast[x]=trlen;
}
int id,top,cnt;
int low[510000],dfn[510000],tot[510000],s[510000];
int sta[510000],belong[510000],sans[510000],list[510000];
bool v[510000],bk[510000];
void dfs(int x)
{
dfn[x]=low[x]=++id;
sta[++top]=x;v[x]=true;
for(int k=last[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(v[y]==true)low[x]=min(low[x],dfn[y]);
}
}
if(low[x]==dfn[x])
{
cnt++;int i;
do
{
i=sta[top--];
v[i]=false;
tot[cnt]+=s[i];
belong[i]=cnt;
}while(i!=x);
}
}
int main()
{
len=0;memset(last,0,sizeof(last));
memset(bk,false,sizeof(bk));
int n,m,ss,p;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
ins(x,y);
}
for(int i=1;i<=n;i++)scanf("%d",&s[i]);
scanf("%d%d",&ss,&p);
for(int i=1;i<=p;i++)
{
int x;
scanf("%d",&x);
bk[x]=true;
}
id=cnt=top=0;
memset(dfn,-1,sizeof(dfn));
memset(low,0,sizeof(low));
memset(sta,0,sizeof(sta));
memset(belong,0,sizeof(belong));
memset(tot,0,sizeof(tot));
for(int i=1;i<=n;i++)
{
if(dfn[i]==-1)dfs(i);
}
trlen=0;memset(trlast,0,sizeof(trlast));
for(int i=1;i<=len;i++)
{
if(belong[a[i].x]!=belong[a[i].y])trins(belong[a[i].x],belong[a[i].y],tot[belong[a[i].x]]);
}
int st,ed=cnt+1;
for(int i=1;i<=n;i++)
{
if(i==ss)st=belong[i];
if(bk[i]==true)trins(belong[i],ed,tot[belong[i]]);
}
memset(v,true,sizeof(v));
memset(sans,-1,sizeof(sans));
int head=1,tail=2;
list[head]=st;sans[st]=0;v[st]=false;
while(head!=tail)
{
int x=list[head];
for(int k=trlast[x];k;k=tr[k].next)
{
int y=tr[k].y;
if(sans[y]<sans[x]+tr[k].c)
{
sans[y]=sans[x]+tr[k].c;
if(v[y]==true)
{
v[y]=false;
list[tail++]=y;
if(tail==500001)tail=1;
}
}
}
v[x]=true;
head++;
if(head==500001)head=1;
}
printf("%d\n",sans[ed]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  bzoj Apio spfa 强联通