图论(强连通分量):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 }
尽最大的努力,做最好的自己!