图论(强连通分量):BZOJ 1179 [Apio2009]Atm

  这题算是一道图论好题了,先用Kosaraju算法求强连通分量,然后缩点跑最长路,这里必须用Spfa,不能用dijkstra算法。

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 using namespace std;
  5 const int maxn=500010,maxm=500010;
  6 struct Edge{
  7     int fir[maxn],nxt[maxm],to[maxm],cnt;
  8     void addedge(int a,int b){
  9         nxt[++cnt]=fir[a];
 10         to[cnt]=b;
 11         fir[a]=cnt;
 12     }
 13 }e,g,re;
 14 
 15 
 16 bool bar[maxn];
 17 bool vis[maxn];
 18 
 19 int st[maxn],cnt;
 20 int q[maxn*10],front,back;
 21 void DFS(int node){
 22     vis[node]=true;
 23     for(int i=e.fir[node];i;i=e.nxt[i])
 24         if(!vis[e.to[i]])
 25             DFS(e.to[i]);
 26     st[++cnt]=node;
 27 }
 28 
 29 int K;
 30 int dot[maxn];
 31 int val[maxn];
 32 int ATM[maxn];
 33 int dis[maxn];
 34 void reDFS(int node,int num){
 35     vis[node]=true;dot[node]=num;
 36     for(int i=re.fir[node];i;i=re.nxt[i])
 37         if(!vis[re.to[i]])
 38             reDFS(re.to[i],num);
 39 }
 40 
 41 void BFS(int S)
 42 {
 43     front=back=1;
 44     q[back++]=S;
 45     vis[S]=0;
 46     memset(dis,0x80,sizeof(dis));
 47     dis[S]=val[S];
 48     while(front<back)
 49     {
 50         int node=q[front++];vis[node]=false;
 51         for(int i=g.fir[node];i;i=g.nxt[i])
 52             if(dis[g.to[i]]<dis[node]+val[g.to[i]]){
 53                 dis[g.to[i]]=dis[node]+val[g.to[i]];
 54                 if(!vis[g.to[i]]){
 55                     q[back++]=g.to[i];
 56                     vis[g.to[i]]=true;
 57                 }
 58             }
 59     }
 60 }
 61 
 62 int main()
 63 {
 64     int n,m,a,b,S,P;
 65     scanf("%d%d",&n,&m);
 66     for(int i=1;i<=m;i++){
 67         scanf("%d%d",&a,&b);
 68         e.addedge(a,b);
 69         re.addedge(b,a);
 70     }
 71     for(int i=1;i<=n;i++){
 72         scanf("%d",&a);
 73         ATM[i]=a;
 74     }
 75     scanf("%d%d",&S,&P);
 76     for(int i=1;i<=P;i++){
 77         scanf("%d",&a);
 78         bar[a]=true;
 79     }
 80     
 81     for(int i=1;i<=n;i++)
 82         if(!vis[i])
 83             DFS(i);
 84             
 85     memset(vis,0,sizeof(vis));
 86     for(int i=cnt;i>=1;i--)
 87         if(!vis[st[i]])
 88             reDFS(st[i],++K);
 89     memset(vis,0,sizeof(vis));
 90     for(int node=1;node<=n;node++){
 91         for(int i=e.fir[node];i;i=e.nxt[i])
 92             if(dot[node]!=dot[e.to[i]])
 93                 g.addedge(dot[node],dot[e.to[i]]);
 94     }    
 95     for(int i=1;i<=n;i++)
 96         val[dot[i]]+=ATM[i];
 97     
 98     
 99     memset(vis,0,sizeof(vis));
100     BFS(dot[S]);
101     int ans=0;
102     for(int i=1;i<=n;i++)
103         if(bar[i])
104             ans=max(ans,dis[dot[i]]);
105     printf("%d\n",ans);    
106 }

 

posted @ 2016-03-14 14:20  TenderRun  阅读(251)  评论(2编辑  收藏  举报