当前位置:   article > 正文

2018 Benelux Algorithm Programming Contest (BAPC 18) I.In Case of an Invasion, Please...(网络流+最短路)

in case of an invasion, please...

题目

思路来源

http://blog.leanote.com/post/icontofig/e6b30008ad99

题解

怎么会不觉得自己sb呢,本来是很裸的网络流题

预处理最短路,每个点到避难所的距离

挑战原题的思路,首先二分最小时间t,每个居民只能去小于等于t的避难所,

于是就变成一个匹配问题,类似地跑网络流,

左源右汇,中间两层,一层是实际的点,一层是避难所

但是1e5个点,乘上二分的复杂度会t

注意到避难所只有10个,所以可以把到避难所连通性相同的点合并到一起,

这样实际的点就只有1<<10个了

 

注意到答案一定是最短路的每个时间,所以可以离散化这个时间,

从而二分最短路数组中的值,减小常数

代码

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<queue>
  5. #include<map>
  6. #include<algorithm>
  7. using namespace std;
  8. typedef long long ll;
  9. #define fi first
  10. #define se second
  11. #define pb push_back
  12. typedef pair<int,int> P;
  13. const ll inf=0x3f3f3f3f3f3f3f3fll;
  14. const int INF=0x3f3f3f3f,maxn=1e5+10,maxm=2e6+4e5+10,M=(1<<10)+5;
  15. int level[maxn],p[maxn];
  16. ll dis[11][maxn],d[maxm],all,c;
  17. bool vis[maxn];
  18. int head[maxn],cnt;
  19. int n,m,s,up[maxn];
  20. int st[maxn];//state
  21. ll sum[M];
  22. struct node{
  23. ll v;
  24. int id;
  25. bool operator<(const node &x)const{
  26. return v>x.v;
  27. }
  28. };
  29. struct edge{
  30. int v,nex;
  31. ll w;
  32. }e[maxm];
  33. void init(){
  34. cnt=0;
  35. memset(head,-1,sizeof head);
  36. memset(sum,0,sizeof sum);
  37. }
  38. void add(int u,int v,ll w){
  39. e[cnt].v=v;
  40. e[cnt].w=w;
  41. e[cnt].nex=head[u];
  42. head[u]=cnt++;
  43. }
  44. void add2(int u,int v,ll w,bool op) {
  45. add(u,v,w);
  46. add(v,u,op?0:w);
  47. }
  48. void dijkstra(int x,int s){
  49. memset(vis,0,sizeof vis);
  50. priority_queue<node>q;
  51. q.push(node{0,s});
  52. dis[x][s]=0;
  53. while(!q.empty()){
  54. node y=q.top();
  55. q.pop();
  56. d[++c]=y.v;
  57. int id=y.id;
  58. if(vis[id])continue;
  59. vis[id]=1;
  60. for(int i=head[id];~i;i=e[i].nex){
  61. int to=e[i].v;ll w=e[i].w;
  62. if(dis[x][to]>dis[x][id]+w){
  63. dis[x][to]=dis[x][id]+w;
  64. q.push(node{dis[x][to],to});
  65. }
  66. }
  67. }
  68. }
  69. bool bfs(int s,int t){
  70. queue<int>q;
  71. memset(level,0,sizeof level);
  72. level[s]=1;
  73. q.push(s);
  74. while(!q.empty()){
  75. int x=q.front();
  76. q.pop();
  77. if(x==t)return 1;
  78. for(int u=head[x];~u;u=e[u].nex){
  79. int v=e[u].v;ll w=e[u].w;
  80. if(!level[v]&&w){
  81. level[v]=level[x]+1;
  82. q.push(v);
  83. }
  84. }
  85. }
  86. return 0;
  87. }
  88. ll dfs(int u,ll maxf,int t){
  89. if(u==t)return maxf;
  90. ll ret=0;
  91. for(int i=head[u];~i;i=e[i].nex){
  92. int v=e[i].v;ll w=e[i].w;
  93. if(level[u]+1==level[v]&&w){
  94. ll MIN=min(maxf-ret,w);
  95. w=dfs(v,MIN,t);
  96. e[i].w-=w;
  97. e[i^1].w+=w;
  98. ret+=w;
  99. if(ret==maxf)break;
  100. }
  101. }
  102. if(!ret)level[u]=-1;//优化,防止重搜,说明u这一路不可能有流量了
  103. return ret;
  104. }
  105. ll Dinic(int s,int t){
  106. ll ans=0;
  107. while(bfs(s,t))
  108. ans+=dfs(s,INF,t);
  109. return ans;
  110. }
  111. bool ok(ll x){
  112. init();
  113. for(int j=1;j<=n;++j){
  114. st[j]=0;
  115. for(int i=1;i<=s;++i){
  116. if(dis[i][j]>x)continue;
  117. st[j]|=(1<<(i-1));
  118. }
  119. sum[st[j]]+=p[j];
  120. }
  121. int mx=1<<s;
  122. int st=mx+s+1,ed=mx+s+2;
  123. for(int i=0;i<mx;++i){
  124. if(!sum[i])continue;
  125. add2(st,i,sum[i],1);
  126. for(int j=0;j<s;++j){
  127. if(i>>j&1){
  128. add2(i,mx+j+1,sum[i],1);
  129. }
  130. }
  131. }
  132. for(int i=1;i<=s;++i){
  133. add2(mx+i,ed,up[i],1);
  134. }
  135. return Dinic(st,ed)==all;
  136. }
  137. int main(){
  138. init();
  139. memset(dis,inf,sizeof dis);
  140. scanf("%d%d%d",&n,&m,&s);
  141. for(int i=1;i<=n;++i){
  142. scanf("%d",&p[i]);
  143. all+=p[i];
  144. }
  145. while(m--){
  146. int x,y,w;
  147. scanf("%d%d%d",&x,&y,&w);
  148. add2(x,y,w,0);
  149. }
  150. for(int i=1;i<=s;++i){
  151. int v;
  152. scanf("%d%d",&v,&up[i]);
  153. dijkstra(i,v);
  154. //for(int j=1;j<=n;++j){
  155. //printf("i:%d j:%d dis:%lld\n",i,j,dis[i][j]);
  156. //}
  157. }
  158. sort(d+1,d+c+1);
  159. c=unique(d+1,d+c+1)-(d+1);
  160. ll l=1,r=c;
  161. while(l<=r){
  162. ll mid=(l+r)>>1;
  163. if(ok(d[mid])){
  164. r=mid-1;
  165. }
  166. else{
  167. l=mid+1;
  168. }
  169. }
  170. printf("%lld\n",d[l]);
  171. return 0;
  172. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/281706
推荐阅读
  

闽ICP备14008679号