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

bzoj 1497 [NOI2006]最大获利最大权闭合子图+最小割

bzoj1497: [NOI2006]最大获利

AC日记——[NOI2006]最大获利 bzoj 1497

BZOJ1497: [NOI2006]最大获利