1. 程式人生 > >洛谷 P3627 [APIO2009]搶掠計劃

洛谷 P3627 [APIO2009]搶掠計劃

最大 lin hid next mat 思路 pri top num

這題一看就是縮點,但是縮完點怎麽辦呢?首先我們把所有的包含酒吧的縮點找出來,打上標記,然後建立一張新圖,

每個縮點上的點權就是他所包含的所有點的點權和。但是建圖的時候要註意,每一對縮點之間可能有多條邊,所以我們可以先把重邊去除一下,在建立新圖,具體操作如下:

技術分享圖片
 1 for(int i=1;i<=n;i++)
 2     {
 3         if(vis[i]==0) continue;
 4         for(int j=last[i];j;j=g[j].next)
 5         {
 6             int v=g[j].to;
 7             if
(g[i].co!=g[v].co&&vis[v]==1) 8 { 9 e[++cnt].a=g[i].co; 10 e[cnt].b=g[v].co; 11 } 12 } 13 } 14 sort(e+1,e+cnt+1,cmp); 15 for(int i=1;i<=cnt;i++) 16 { 17 if(e[i].a!=e[i-1].a||e[i].b!=e[i-1].b) 18 {
19 add1(e[i].a,e[i].b); 20 } 21 }
View Code

具體思路就是先枚舉所有點和所有邊,如果兩個點不屬於同一個強聯通分量,那麽就用e來把邊存一下,然後對e進行排序

,去重,再建圖。

建玩圖之後就好辦了,可以跑spfa單源最長路,也可以dp,因為最後一定會終止在酒吧,所以就取所有打過標記的節點的最大值就好了。

最後附上代碼:

技術分享圖片
  1 #include<iostream>
  2 #include<cmath>
  3 #include<cstdio>
  4
#include<string> 5 #include<cstring> 6 #include<algorithm> 7 #define maxn 500005 8 using namespace std; 9 struct edge 10 { 11 int next; 12 int to; 13 int co; 14 }g[maxn]; 15 16 struct edge1 17 { 18 int next; 19 int to; 20 }g1[maxn]; 21 struct edhe 22 { 23 int a,b; 24 }e[maxn]; 25 26 27 inline int read() 28 { 29 char c=getchar(); 30 int res=0,x=1; 31 while(c<0||c>9) 32 { 33 if(c==-) 34 x=-1; 35 c=getchar(); 36 } 37 while(c>=0&&c<=9) 38 { 39 res=res*10+(c-0); 40 c=getchar(); 41 } 42 return x*res; 43 } 44 45 int n,m,aa,bb,num,s,p,tot,top,col,num1,ans,ae,cnt; 46 int last[maxn],a[maxn],b[maxn],dfn[maxn],st[maxn],low[maxn]; 47 int shu[maxn],d[maxn],last1[maxn],sum[maxn],vis[maxn]; 48 49 inline void add(int from,int to) 50 { 51 g[++num].next=last[from]; 52 g[num].to=to; 53 last[from]=num; 54 } 55 56 inline void add1(int from,int to) 57 { 58 g1[++num1].next=last1[from]; 59 g1[num1].to=to; 60 last1[from]=num1; 61 } 62 63 inline void tarjan(int u) 64 { 65 low[u]=dfn[u]=++tot; 66 st[++top]=u; 67 for(int i=last[u];i;i=g[i].next) 68 { 69 int v=g[i].to; 70 if(!dfn[v]) 71 { 72 tarjan(v); 73 if(low[v]<low[u]) 74 low[u]=low[v]; 75 } 76 else if(!g[v].co) 77 { 78 if(dfn[v]<low[u]) 79 low[u]=dfn[v]; 80 } 81 } 82 if(low[u]==dfn[u]) 83 { 84 g[u].co=++col; 85 while(st[top]!=u) 86 { 87 g[st[top]].co=col; 88 top--; 89 } 90 top--; 91 } 92 } 93 94 void dfs(int x) 95 { 96 for(int i=last1[x];i;i=g1[i].next) 97 { 98 int v=g1[i].to; 99 if(sum[x]+shu[v]>sum[v]) 100 { 101 sum[v]=sum[x]+shu[v]; 102 dfs(v); 103 } 104 } 105 } 106 107 bool cmp(edhe a,edhe b) 108 { 109 if(a.a==b.a) 110 { 111 return a.b<b.b; 112 } 113 else return a.a<b.a; 114 } 115 116 int main() 117 { 118 n=read(); 119 m=read(); 120 for(int i=1;i<=m;i++) 121 { 122 aa=read();bb=read(); 123 add(aa,bb); 124 } 125 for(int i=1;i<=n;i++) 126 { 127 a[i]=read(); 128 } 129 s=read();p=read(); 130 for(int i=1;i<=p;i++) 131 { 132 aa=read(); 133 b[aa]=1; 134 } 135 for(int i=1;i<=n;i++) 136 { 137 if(!dfn[i]) 138 tarjan(i); 139 } 140 for(int i=1;i<=n;i++) 141 { 142 shu[g[i].co]+=a[i]; 143 if(b[i]==1) 144 { 145 d[g[i].co]=1; 146 } 147 } 148 for(int i=1;i<=n;i++) 149 { 150 if(vis[i]==0) continue; 151 for(int j=last[i];j;j=g[j].next) 152 { 153 int v=g[j].to; 154 if(g[i].co!=g[v].co) 155 { 156 e[++cnt].a=g[i].co; 157 e[cnt].b=g[v].co; 158 } 159 } 160 } 161 sort(e+1,e+cnt+1,cmp); 162 for(int i=1;i<=cnt;i++) 163 { 164 if(e[i].a!=e[i-1].a||e[i].b!=e[i-1].b) 165 { 166 add1(e[i].a,e[i].b); 167 } 168 } 169 sum[g[s].co]=shu[g[s].co]; 170 dfs(g[s].co); 171 for(int i=1;i<=col;i++) 172 { 173 if(d[i]==1) 174 { 175 if(ans<sum[i]) 176 ans=sum[i]; 177 } 178 } 179 printf("%d",ans); 180 return 0; 181 }
View Code

洛谷 P3627 [APIO2009]搶掠計劃