【BZOJ1179】 [Apio2009]Atm tarjan缩点+SPFA

Description

Input

第一行包含两个整数N、M。N表示路口的个数,M表示道路条数。接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号。接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数。接下来一行包含两个整数S、P,S表示市中心的编号,也就是出发的路口。P表示酒吧数目。接下来的一行中有P个整数,表示P个有酒吧的路口的编号

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

HINT

 

50%的输入保证N, M<=3000。所有的输入保证N, M<=500000。每个ATM机中可取的钱数为一个非负整数且不超过4000。输入数据保证你可以从市中心沿着Siruseri的单向的道路到达其中的至少一个酒吧。

 

Source

1A大法爽,由于没有时间的限制,但又因为抢过的ATM没钱了,所以可以tarjan求还然后缩点,再SPFA加了点读入优化,发现慢的1B,WHY?,好像这道T可以DP啊。。。太弱了我。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <queue>
  6 #include <stack>
  7 #define N 500500
  8 #define M 500500
  9 using namespace std;
 10 struct data{int next,p;}e1[M],e2[M];
 11 int head1[N],head2[N],belong[N],low[N],dfn[N],mon[N],vscc[N],dis[N],inq[N],vis[N];
 12 int q1[N],q[N];
 13 int n,m,S,p,cnt,ans,qt,scc;
 14 inline int max(int x,int y){return x>y?x:y;}
 15 inline int min(int x,int y){return x<y?x:y;}
 16 inline int read()
 17 {
 18     char c;
 19     int anss=0;
 20     while ((c=getchar())==' ' || c=='\n' || c=='\r');
 21     anss=c-'0';
 22     while (isdigit(c=getchar())) anss=anss*10+c-'0';
 23     return anss;
 24 }
 25 void se1(int x,int y){cnt++; e1[cnt].next=head1[x]; head1[x]=cnt; e1[cnt].p=y;}
 26 void se2(int x,int y){cnt++; e2[cnt].next=head2[x]; head2[x]=cnt; e2[cnt].p=y;}
 27 void tarjan(int x)
 28 {
 29     vis[x]=inq[x]=1;
 30     dfn[x]=low[x]=++cnt;
 31     q1[++qt]=x;
 32     for (int i=head1[x];i;i=e1[i].next)
 33     {
 34         if (!vis[e1[i].p])
 35         {
 36             tarjan(e1[i].p);
 37             low[x]=min(low[x],low[e1[i].p]);
 38         }
 39         else if (inq[e1[i].p])    low[x]=min(low[x],low[e1[i].p]);
 40     }
 41     if (low[x]==dfn[x])
 42     {
 43         int now=0;
 44         scc++;
 45         while (now!=x)
 46         {
 47             now=q1[qt];qt--;
 48             belong[now]=scc;
 49             inq[now]=0;
 50             vscc[scc]+=mon[now];
 51         }
 52     }
 53 }
 54 void part1_tarjan()
 55 {
 56     cnt=0;
 57     for (int i=1;i<=n;i++)
 58         if (!vis[i])    tarjan(i);
 59 }
 60 void part2_shr_point()
 61 {
 62     cnt=0;
 63     for (int i=1;i<=n;i++)
 64         for (int j=head1[i];j;j=e1[j].next)
 65             if (belong[i]!=belong[e1[j].p])
 66                 se2(belong[i],belong[e1[j].p]);
 67 }
 68 void part3_spfa()
 69 {
 70     memset(inq,0,sizeof(inq));
 71     int t=0,w=1;
 72     q[t]=belong[S];
 73     inq[belong[S]]=1;
 74     dis[belong[S]]=vscc[belong[S]];
 75     while  (t!=w)
 76     {
 77         int now=q[t];t++;
 78         for (int i=head2[now];i;i=e2[i].next)
 79             if (dis[e2[i].p]<dis[now]+vscc[e2[i].p])
 80             {
 81                 dis[e2[i].p]=dis[now]+vscc[e2[i].p];
 82                 if (!inq[e2[i].p])
 83                 {
 84                     inq[e2[i].p]=1;
 85                     q[w++]=e2[i].p;
 86                 }
 87             }
 88         inq[now]=0;
 89     }
 90 }
 91 int main()
 92 {
 93     n=read();m=read();
 94     for (int i=1;i<=m;i++)    
 95     {
 96         int x,y;
 97         x=read();y=read();
 98         se1(x,y);
 99     }
100     for (int i=1;i<=n;i++)    mon[i]=read();
101     part1_tarjan();
102     part2_shr_point();
103     S=read();p=read();
104     part3_spfa();
105     for (int i=1;i<=p;i++)
106     {
107         int x=read();
108         if (dis[belong[x]]>ans) ans=dis[belong[x]];
109     }
110     printf("%d\n",ans);
111     return 0;
112 }
View Code

 

posted @ 2016-03-08 20:18  DMoon  阅读(146)  评论(0编辑  收藏  举报