[bzoj]1179 ATM

1179: [Apio2009]Atm

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 4645  Solved: 2054
[Submit][Status][Discuss]

Description

Siruseri 城中的道路都是单向的。不同的道路由路口连接。按照法律的规定, 在每个路口都设立了一个 Siruser
i 银行的 ATM 取款机。令人奇怪的是,Siruseri 的酒吧也都设在路口,虽然并不是每个路口都设有酒吧。Bandit
ji 计划实施 Siruseri 有史以来最惊天动地的 ATM 抢劫。他将从市中心 出发,沿着单向道路行驶,抢劫所有他
途径的 ATM 机,最终他将在一个酒吧庆 祝他的胜利。使用高超的黑客技术,他获知了每个 ATM 机中可以掠取的
现金数额。他希 望你帮助他计算从市中心出发最后到达某个酒吧时最多能抢劫的现金总数。他可 以经过同一路口
或道路任意多次。但只要他抢劫过某个 ATM 机后,该 ATM 机 里面就不会再有钱了。 例如,假设该城中有 6 个
路口,道路的连接情况如下图所示:
市中心在路口 1,由一个入口符号→来标识,那些有酒吧的路口用双圈来表示。每个 ATM 机中可取的钱数标在了
路口的上方。在这个例子中,Banditji 能抢 劫的现金总数为 47,实施的抢劫路线是:1-2-4-1-2-3-5。

Input

第一行包含两个整数N、M。N表示路口的个数,M表示道路条数。
接下来M行,每行两个整数,这两个整数都在1到N之间,
第i+1行的两个整数表示第i条道路的起点和终点的路口编号。
接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数。
接下来一行包含两个整数S、P,S表示市中心的编号,也就是出发的路口。P表示酒吧数目。
接下来的一行中有P个整数,表示P个有酒吧的路口的编号
N, M<=500000。每个ATM机中可取的钱数为一个非负整数且不超过4000。
输入数据保证你可以从市中心沿着Siruseri的单向的道路到达其中的至少一个酒吧。

Output

输出一个整数,表示Banditji从市中心开始到某个酒吧结束所能抢劫的最多的现金总数。

Sample Input

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

Sample Output

47

Tarjan缩点之后,跑一遍spfa求最长路就行了。

中间因为变量,初始化问题死了好多次,我会在代码里写出我给自己挖的坑。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<cstdlib>
  5 #include<algorithm>
  6 #include<cmath>
  7 #include<vector>
  8 #include<stack>
  9 #include<map>
 10 using namespace std;
 11 #define mem(a,b) memset(a,b,sizeof(a))
 12 #define ll long long
 13 #define inf 1000000000
 14 #define maxn 500000+100
 15 #define maxm 500000+100
 16 struct node
 17 {
 18     int to,next;
 19 } edge[maxm];
 20 int n,m,head[maxn],vis[maxn],dfn[maxn],low[maxn],cdu[maxn],num[maxn],cnt,timi,stack1[maxn],top,cut,rdu[maxn];
 21 int mon[maxn],jiu[maxn],ss,p,from[maxn],go[maxn],s1[maxn],d[maxn],q[maxn],c[maxn];
 22 stack <int> s;
 23 inline int read()
 24   {
 25       int x=0,f=1;char ch=getchar();
 26       while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
 27       while(ch>='0'&&ch<='9') {x=10*x+ch-'0';ch=getchar();}
 28       return x*f;
 29   }
 30 void init()
 31 {
 32     memset(dfn,0,sizeof(dfn));
 33     memset(low,0,sizeof(low));
 34     memset(head,-1,sizeof(head));
 35     memset(vis,0,sizeof(vis));
 36     memset(num,0,sizeof(num));
 37     memset(cdu,0,sizeof(cdu));
 38     memset(rdu,0,sizeof(rdu));
 39     mem(jiu,0);
 40     mem(c,0);
 41     //while(!s.empty()) s.pop();
 42     cnt=0;
 43     timi=1;
 44     top=0;
 45     cut=0;
 46 }
 47 void addedge(int u,int v)
 48 {
 49     edge[cnt].to=v;
 50     edge[cnt].next=head[u];
 51     head[u]=cnt;
 52     cnt++;
 53 }
 54 void tarjan(int u)
 55 {
 56     dfn[u]=timi;
 57     low[u]=timi;
 58     timi++;
 59     s.push(u);
 60     vis[u]=1;
 61     for(int i=head[u]; i!=-1; i=edge[i].next)
 62     {
 63         int v=edge[i].to;
 64         if(!dfn[v])
 65         {
 66             tarjan(v);
 67             low[u]=min(low[u],low[v]);
 68         }
 69         else
 70         {
 71             if(vis[v])
 72                 low[u]=min(low[u],dfn[v]);
 73         }
 74     }
 75     if(low[u]==dfn[u])
 76     {
 77         cut++;
 78         int x=s.top();
 79         while(x!=u)
 80         {
 81             vis[x]=0;
 82             num[x]=cut;
 83             s1[cut]+=mon[x];
 84             //printf("cut=%d s1=%d \n",cut,s1[cut]);
 85             if(jiu[x]) c[cut]=1;
 86             s.pop();
 87             x=s.top();
 88         }
 89         num[x]=cut;
 90         s1[cut]+=mon[x];//我今天又在这里死了,你不能因为人家在外面你就不管人家啊。。瞎浪
 91         if(jiu[x]) c[cut]=1;
 92         //printf("cut=%d s1=%d \n",cut,s1[cut]);
 93         vis[x]=0;
 94         s.pop();
 95     }
 96 }
 97 void spfa()
 98 {
 99     for(int i=1;i<=cut;++i) d[i]=0;
100     mem(vis,0);
101     int l=0,r=1,x,y;
102     
103     q[1]=num[ss];d[num[ss]]=s1[num[ss]];
104     //cout<<q[1]<<endl;
105     //cout<<l<<" "<<r<<endl;
106     while(l!=r)
107     {
108         x=q[++l];
109         //cout<<head[x]<<endl;
110         if(l==maxn) l=0;vis[x]=0;
111         for(int i=head[x];i!=-1;i=edge[i].next)
112         {
113          // cout<<"i="<<i<<endl;
114             if(d[x]+s1[y=edge[i].to]>d[y])
115             {
116                 d[y]=d[x]+s1[y];
117                // cout<<"y="<<y<<endl;
118                 if(!vis[y])
119                 {
120                     vis[y]=1;q[++r]=y;if(r==maxn) r=0;
121                 }
122             }
123         }
124     }
125 }
126 int main()
127 {
128    init();//第一次跑不出来死在这里,没有初始化,今天在这个地方死第二次了(微笑
129    int x,y;
130    n=read();m=read();
131    for(int i=1;i<=m;++i)
132    {
133        int a,b;
134        a=read();b=read();
135        from[i]=a;go[i]=b;
136        addedge(a,b);
137    }
138    for(int i=1;i<=n;++i) mon[i]=read();
139    ss=read();p=read();
140    for(int i=1;i<=p;++i)
141    {
142        int h=read();jiu[h]=1;
143    }
144    for(int i=1;i<=n;++i)
145     if(!dfn[i]) tarjan(i);
146    mem(head,-1);
147    cnt=0;
148    for(int i=1;i<=m;++i)
149    {
150        if(num[x=from[i]]!=num[y=go[i]]) addedge(num[x],num[y]);//最后发现死在了这里,我真的是zz,缩点后不用缩点。。
151    }
152    spfa();
153    int ans=0;
154    //for(int i=1;i<=n;++i) cout<<num[i]<<" "<<mon[i]<<endl;
155    //cout<<cut<<endl;
156    //for(int i=1;i<=cut;++i) cout<<s1[i]<<endl;
157    for(int i=1;i<=cut;++i) if(c[i]) ans=max(ans,d[i]);
158    cout<<ans<<endl;
159 }
View Code

 

posted @ 2018-07-31 20:30  Maydaytyh  阅读(233)  评论(0编辑  收藏  举报