[BZOJ 1179][APIO 2009]Atm

來源:互聯網
上載者:User

標籤:style   http   io   ar   os   sp   for   on   div   

題目連結:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1179

個人感覺此題比省選題簡單多了,大概是POJ中檔題的難度。。。

首先我們把這個有向圖縮個點,縮點後的圖是個DAG,新圖中每個點的權值是對應強連通分量中的點的權值之和,新圖中每個點對應的強連通分量中的點都是相互可達的,也就是說新圖中的每個點,劫匪都能一次性搶完其中所有ATM機的錢。

然後對這個新圖跑SPFA,SPFA本來是搞邊權的,在這個題裡,把SPFA稍微改改就能跑點權了,類似於NOIP的最優貿易那個題,很簡單。

最後枚舉所有終點,找出能夠得到最多錢的那個終點就行了。

#include <iostream>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <algorithm>#define MAXE 500050#define MAXV 500050using namespace std;struct edge{    int u,v,next;}edges1[MAXE],edges2[MAXE]; //縮點前的圖、縮點後的圖int nCount1=0,nCount2=0,head1[MAXV],head2[MAXV],money[MAXV]; //money[i]=原圖中點i的錢數int dfn[MAXV],low[MAXV],cnt=0,belong[MAXV],value[MAXV],tot=0; //value[i]=第i號聯通塊中的ATM機金額總數,tot=強連通分量總數bool visit[MAXV];int stack[MAXV],top=0;int n,m,S,P;void AddEdge1(int U,int V){    edges1[++nCount1].u=U;    edges1[nCount1].v=V;    edges1[nCount1].next=head1[U];    head1[U]=nCount1;}void AddEdge2(int U,int V){    edges2[++nCount2].u=U;    edges2[nCount2].v=V;    edges2[nCount2].next=head2[U];    head2[U]=nCount2;}void tarjan(int u){    low[u]=dfn[u]=++cnt;    visit[u]=true;    stack[++top]=u;    for(int p=head1[u];p!=-1;p=edges1[p].next)    {        int v=edges1[p].v;        if(!dfn[v])        {            tarjan(v);            low[u]=min(low[u],low[v]);        }        else if(visit[v])            low[u]=min(low[u],dfn[v]);    }    if(dfn[u]==low[u])    {        tot++;        int v=-1;        while(u!=v)        {            v=stack[top--];            belong[v]=tot;            value[tot]+=money[v];            visit[v]=false;        }    }}void rebuild() //縮點建立新圖{    for(int u=1;u<=n;u++)        for(int p=head1[u];p!=-1;p=edges1[p].next)        {            int v=edges1[p].v;            if(belong[u]!=belong[v])                AddEdge2(belong[u],belong[v]);        }}int f[MAXV],q[MAXV]; //f[i]=從起點到點i時搶到的最多錢數bool inQueue[MAXV];void SPFA(){    int h=0,t=1;    q[h]=belong[S];    inQueue[belong[S]]=true;    f[belong[S]]=value[belong[S]];    while(h<t)    {        int u=q[h++];        inQueue[u]=false;        if(h==MAXV-1) h=0; //迴圈利用隊列,防止RE        for(int p=head2[u];p!=-1;p=edges2[p].next)        {            int v=edges2[p].v;            if(f[u]+value[v]>f[v])            {                f[v]=f[u]+value[v];                if(!inQueue[v])                {                    inQueue[v]=true;                    q[t++]=v;                    if(t==MAXV-1) t=0; //迴圈利用隊列,防止RE                }            }        }    }}int main(){    int ans=0;    memset(head1,-1,sizeof(head1));    memset(head2,-1,sizeof(head2));    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++)    {        int u,v;        scanf("%d%d",&u,&v);        AddEdge1(u,v);    }    for(int i=1;i<=n;i++)        scanf("%d",&money[i]);    for(int i=1;i<=n;i++)        if(!dfn[i])            tarjan(i);    scanf("%d%d",&S,&P);    rebuild(); //建立縮點後的新圖    SPFA();    for(int i=1;i<=P;i++)    {        int x;        scanf("%d",&x);        if(f[belong[x]]>ans) ans=f[belong[x]];    }    printf("%d\n",ans);    return 0;}




[BZOJ 1179][APIO 2009]Atm

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.