BZOJ1179: [Apio2009]Atm

【传送门:BZOJ1179


简要题意:

  有n个城市,其中有一座中心城市,m条单向的道路连接城市,每一个城市里都可以获得钱,而有部分城市有酒吧,不限步数,每条道路可以重复走,但是一个城市里的钱不能重复获取,要求从中心城市出发,到任意一个有酒吧的城市所能获得的最大钱数

此处更正一下BZOJ的样例输入数据:

6 7
1 2
2 3
3 5
2 4
4 1
2 6
6 5
10
12
8
16
1
5
1 4
4 3 5 6


题解:

  因为有可能出现环,而且样例输入数据就出现了(很温馨的数据),所以我们先用强联通来缩点,然后将每个强联通之间通过原来的边来建新的边,直接跑最短路得出答案(因为我是蒟蒻,不懂拓扑,只好这样做了QAQ)


参考代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
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;
}
int d[510000];
bool v[510000];
int sta[510000],tp;
int belong[510000],cnt;
int low[510000],dfn[510000],id;
bool b[510000];
void dfs(int x)
{
    dfn[x]=low[x]=++id;
    sta[++tp]=x;v[x]=true;
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(dfn[y]==0)
        {
            dfs(y);
            low[x]=min(low[x],low[y]);
        }
        else
        {
            if(v[y]==true) low[x]=min(low[x],low[y]);
        }
    }
    if(low[x]==dfn[x])
    {
        int i;cnt++;
        do
        {
            i=sta[tp--];
            belong[i]=cnt;
            v[i]=false;
        }while(i!=x);
    }
}
struct SPFA
{
    int x,y,d,next;
}e[510000];int elen,elast[510000];
int list[510000];
int head,tail;
void eins(int x,int y,int d)
{
    elen++;
    e[elen].x=x;e[elen].y=y;e[elen].d=d;
    e[elen].next=elast[x];elast[x]=elen;
}
int dep[510000];
bool bo[510000];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        ins(x,y);
    }
    memset(sta,0,sizeof(sta));
    memset(v,false,sizeof(v));
    memset(belong,0,sizeof(belong));
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    id=cnt=tp=0;
    for(int i=1;i<=n;i++)
    {
        if(dfn[i]==0) dfs(i);
    }
    memset(d,0,sizeof(d));
    for(int i=1;i<=n;i++)
    {
        int c;
        scanf("%d",&c);
        d[belong[i]]+=c;
    }
    int st,p;
    scanf("%d%d",&st,&p);
    st=belong[st];
    memset(b,false,sizeof(b));
    for(int i=1;i<=p;i++)
    {
        int x;
        scanf("%d",&x);
        b[belong[x]]=true;
    }
    memset(elast,0,sizeof(elast));elen=0;
    for(int i=1;i<=len;i++)
    {
        int x=a[i].x,y=a[i].y;
        if(belong[x]!=belong[y])
        {
            eins(belong[x],belong[y],d[belong[y]]);
        }
    }
    eins(0,st,d[st]);
    head=1;tail=2;list[1]=0;
    dep[0]=0;
    memset(bo,false,sizeof(bo));bo[0]=true;
    int ans=0;
    while(head!=tail)
    {
        int x=list[head];
        for(int k=elast[x];k;k=e[k].next)
        {
            int y=e[k].y;
            if(dep[y]<dep[x]+e[k].d)
            {
                dep[y]=dep[x]+e[k].d;
                if(b[y]==true) ans=max(ans,dep[y]);
                if(bo[y]==false)
                {
                    bo[y]=true;
                    list[tail++]=y;
                }
            }
        }
        bo[x]=false;head++;
    }
    printf("%d\n",ans);
    return 0;
}

 

 

 

posted @ 2017-09-15 20:49  Star_Feel  阅读(174)  评论(0编辑  收藏  举报