hdu 3667(拆边+最小费用最大流)

来源:互联网 发布:宋慈 知乎 编辑:程序博客网 时间:2024/06/07 05:48

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3667

思路:由于花费的计算方法是a*x*x,因此必须拆边,使得最小费用流模板可用,即变成a*x的形式。具体的拆边方法为:第i次取这条路时费用为(2*i-1)*a (i<=5),每条边的容量为1。如果这条边通过的流量为x,那正好sigma(2*i-1)(1<<i<<x)==x^2。然后就是跑最小费用最大流了。

  1 #include<iostream>  2 #include<cstdio>  3 #include<cstring>  4 #include<algorithm>  5 #include<queue>  6 using namespace std;  7 #define MAXN 222  8 #define MAXM 22222222  9 #define inf 1<<30 10  11 struct Edge{ 12     int v,cap,cost,next; 13 }edge[MAXM]; 14  15 int n,m,k,NE; 16 int head[MAXN]; 17  18 void Insert(int u,int v,int cap,int cost) 19 { 20     edge[NE].v=v; 21     edge[NE].cap=cap; 22     edge[NE].cost=cost; 23     edge[NE].next=head[u]; 24     head[u]=NE++; 25  26     edge[NE].v=u; 27     edge[NE].cap=0; 28     edge[NE].cost=-cost; 29     edge[NE].next=head[v]; 30     head[v]=NE++; 31 } 32  33 int dist[MAXN]; 34 bool mark[MAXN]; 35 int cur[MAXN],pre[MAXN]; 36 bool spfa(int vs,int vt) 37 { 38     memset(mark,false,sizeof(mark)); 39     fill(dist,dist+n+1,inf); 40     dist[vs]=0; 41     queue<int>que; 42     que.push(vs); 43     while(!que.empty()){ 44         int u=que.front(); 45         que.pop(); 46         mark[u]=false; 47         for(int i=head[u];i!=-1;i=edge[i].next){ 48             int v=edge[i].v,cost=edge[i].cost; 49             if(edge[i].cap>0&&dist[u]+cost<dist[v]){ 50                 dist[v]=dist[u]+cost; 51                 pre[v]=u; 52                 cur[v]=i; 53                 if(!mark[v]){ 54                     mark[v]=true; 55                     que.push(v); 56                 } 57             } 58         } 59     } 60     return dist[vt]<inf; 61 } 62  63 int MinCostFlow(int vs,int vt) 64 { 65     int cost=0,flow=0; 66     while(spfa(vs,vt)){ 67         int aug=inf; 68         for(int u=vt;u!=vs;u=pre[u]){ 69             aug=min(aug,edge[cur[u]].cap); 70         } 71         flow+=aug;cost+=dist[vt]*aug; 72         for(int u=vt;u!=vs;u=pre[u]){ 73             edge[cur[u]].cap-=aug; 74             edge[cur[u]^1].cap+=aug; 75         } 76     } 77     if(flow<k)cost=-1; 78     return cost; 79 } 80  81 int main() 82 { 83     int u,v,cost,cap; 84     while(~scanf("%d%d%d",&n,&m,&k)){ 85         NE=0; 86         memset(head,-1,sizeof(head)); 87         while(m--){ 88             scanf("%d%d%d%d",&u,&v,&cost,&cap); 89             for(int i=1;i<=cap;i++){ 90                 Insert(u,v,1,(2*i-1)*cost); 91             } 92         } 93         Insert(0,1,k,0); 94         printf("%d\n",MinCostFlow(0,n)); 95     } 96     return 0; 97 } 98  99 100 101         
View Code

 

0 0