Vijos1352 NOI2006 最大获利 最小权闭合图
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vijos1352 NOI2006 最大获利 最小权闭合图相关的知识,希望对你有一定的参考价值。
Orz胡伯涛《最小割模型在信息学竞赛中的应用》
建图方法:
设立源点S和汇点T,S和用户(共M个)连边,载流量为满足其要求的获利
T和中转站(共N个)连边,载流量为建立该中转站的费用
每个用户向对应的2个中转站连边,载流量为inf
对该图跑一遍最大流,求出最小割f,(∑Ci)-f就是答案
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 6 const int maxV=55005; 7 const int maxE=155005; 8 const int inf=0x3f3f3f3f; 9 10 struct Edge 11 { 12 int to,next; 13 int capacity; 14 15 void assign(int t,int n,int c) 16 { to=t; next=n; capacity=c; } 17 }; 18 19 Edge elist[2*maxE]; 20 int head[maxV]; 21 int ecnt; 22 23 void initEdge() 24 { 25 memset(head,-1,sizeof(head)); 26 ecnt=0; 27 } 28 29 inline void addEdge(int from,int to,int capacity) 30 { 31 elist[ecnt].assign(to,head[from],capacity); 32 head[from]=ecnt++; 33 elist[ecnt].assign(from,head[to],0); 34 head[to]=ecnt++; 35 } 36 37 int N,M; 38 int tot; 39 int sink; //1~M:user M+1~N:station 40 41 void input() 42 { 43 scanf("%d%d",&N,&M); 44 initEdge(); 45 sink=N+M+1; 46 int cost; 47 for(int i=1;i<=N;i++) 48 { 49 scanf("%d",&cost); 50 addEdge(M+i,sink,cost); 51 } 52 tot=0; 53 int v1,v2; 54 for(int i=1;i<=M;i++) 55 { 56 scanf("%d%d%d",&v1,&v2,&cost); 57 tot+=cost; 58 addEdge(i,M+v1,inf); 59 addEdge(i,M+v2,inf); 60 addEdge(0,i,cost); 61 } 62 } 63 64 int layer[maxV]; 65 std::queue<int> que; 66 67 bool bfs() 68 { 69 memset(layer,0,sizeof(layer)); 70 layer[0]=1; 71 que.push(0); 72 while(!que.empty()) 73 { 74 int cur=que.front(); 75 que.pop(); 76 for(int e=head[cur];e!=-1;e=elist[e].next) 77 { 78 int& to=elist[e].to; 79 int& cp=elist[e].capacity; 80 if(!layer[to] && cp) 81 { 82 layer[to]=layer[cur]+1; 83 que.push(to); 84 } 85 } 86 } 87 return layer[sink]; 88 } 89 90 int dfs(int cur,int flow) 91 { 92 if(cur==sink) return flow; 93 int res(0); 94 for(int e=head[cur];e!=-1;e=elist[e].next) 95 { 96 int& to=elist[e].to; 97 int& cp=elist[e].capacity; 98 if(layer[to]==layer[cur]+1 && cp) 99 { 100 int tp=dfs(to,std::min(flow,cp)); 101 res+=tp; flow-=tp; 102 elist[e].capacity-=tp; 103 elist[e^1].capacity+=tp; 104 if(!flow) return res; 105 } 106 } 107 return res; 108 } 109 110 int dinic() 111 { 112 int res(0); 113 while(bfs()) res+=dfs(0,inf); 114 return res; 115 } 116 117 int main() 118 { 119 input(); 120 printf("%d\n",tot-dinic()); 121 return 0; 122 }
以上是关于Vijos1352 NOI2006 最大获利 最小权闭合图的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 1497: [NOI2006]最大获利 -- 最小割
BZOJ1497 [NOI2006]最大获利 网络流 最小割 SAP