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

题目链接: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

 

你可能感兴趣的:(HDU)