洛谷 P3627 [APIO2009]抢掠计划 题解
Analysis
建图+强连通分量+SPFA求最长路
但要保证最后到达的点中包含酒馆
虽然思路并不难想,但要求的代码能力很高。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #define maxn 500010 7 using namespace std; 8 inline int read() 9 { 10 int x=0; 11 bool f=1; 12 char c=getchar(); 13 for(; !isdigit(c); c=getchar()) if(c=='-') f=0; 14 for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0'; 15 if(f) return x; 16 return 0-x; 17 } 18 inline void write(int x) 19 { 20 if(x<0){putchar('-');x=-x;} 21 if(x>9)write(x/10); 22 putchar(x%10+'0'); 23 } 24 struct node 25 { 26 int from,to,val,nex; 27 }edge[2*maxn]; 28 int n,m,s,p,cnt,ans,top,inl,num; 29 int x[maxn],y[maxn],head[maxn],dfn[maxn],low[maxn],st[maxn],inn[maxn],sum[maxn],si[maxn],money[maxn],dis[maxn]; 30 bool book[maxn],book1[maxn],bar[maxn]; 31 inline void clear() 32 { 33 cnt=0; 34 memset(edge,0,sizeof(edge)); 35 memset(head,0,sizeof(head)); 36 } 37 inline void add(int x,int y) 38 { 39 cnt++; 40 edge[cnt].to=y; 41 edge[cnt].nex=head[x]; 42 head[x]=cnt; 43 } 44 inline void build(int x,int y,int z) 45 { 46 cnt++; 47 edge[cnt].from=x; 48 edge[cnt].to=y; 49 edge[cnt].val=z; 50 edge[cnt].nex=head[x]; 51 head[x]=cnt; 52 } 53 inline void Tarjan(int u) 54 { 55 dfn[u]=low[u]=++num; 56 st[++top]=u; 57 for(int i=head[u];i;i=edge[i].nex) 58 { 59 int v=edge[i].to; 60 if(!dfn[v]) 61 { 62 Tarjan(v); 63 low[u]=min(low[u],low[v]); 64 } 65 else if(!inn[v]) 66 low[u]=min(low[u],dfn[v]); 67 } 68 if(low[u]==dfn[u]) 69 { 70 inn[u]=++inl; 71 while(st[top]!=u) 72 { 73 if(bar[st[top]])book1[inl]=1; 74 sum[inl]+=money[st[top]]; 75 inn[st[top]]=inl; 76 --top; 77 } 78 if(bar[st[top]])book1[inl]=1; 79 sum[inl]+=money[st[top]]; 80 --top; 81 } 82 } 83 inline void spfa() 84 { 85 memset(book,0,sizeof(book)); 86 for(int i=1;i<=n;i++) dis[i]=0; 87 queue<int> q; 88 q.push(inn[s]); 89 book[inn[s]]=1; 90 dis[inn[s]]=sum[inn[s]]; 91 while(!q.empty()) 92 { 93 for(int i=head[q.front()];i;i=edge[i].nex) 94 { 95 if(dis[edge[i].to]<dis[edge[i].from]+edge[i].val) 96 { 97 dis[edge[i].to]=dis[edge[i].from]+edge[i].val; 98 if(book[edge[i].to]==0) 99 { 100 q.push(edge[i].to); 101 book[edge[i].to]=1; 102 } 103 } 104 } 105 book[q.front()]=0; 106 q.pop(); 107 } 108 } 109 int main() 110 { 111 n=read();m=read(); 112 for(int i=1;i<=m;i++) 113 { 114 x[i]=read();y[i]=read(); 115 add(x[i],y[i]); 116 } 117 for(int i=1;i<=n;i++)money[i]=read(); 118 s=read();p=read(); 119 120 for(int i=1;i<=p;i++) 121 { 122 int x; 123 x=read(); 124 bar[x]=1; 125 } 126 for(int i=1;i<=n;i++) 127 if(!dfn[i]) 128 Tarjan(i); 129 130 clear(); 131 for(int i=1;i<=m;i++) 132 if(inn[x[i]]!=inn[y[i]]) 133 build(inn[x[i]],inn[y[i]],sum[inn[y[i]]]); 134 spfa(); 135 for(int i=1;i<=inl;i++) 136 if(book1[i]==1) 137 ans=max(ans,dis[i]); 138 write(ans); 139 return 0; 140 }
请各位大佬斧正(反正我不认识斧正是什么意思)