hdu 3667 拆边加最小费用流

Transportation

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2301    Accepted Submission(s): 966


Problem Description
There are N cities, and M directed roads connecting them. Now you want to transport K units of goods from city 1 to city N. There are many robbers on the road, so you must be very careful. The more goods you carry, the more dangerous it is. To be more specific, for each road i, there is a coefficient a i. If you want to carry x units of goods along this road, you should pay a i * x 2 dollars to hire guards to protect your goods. And what’s worse, for each road i, there is an upper bound C i, which means that you cannot transport more than C i units of goods along this road. Please note you can only carry integral unit of goods along each road.
You should find out the minimum cost to transport all the goods safely. 
 

 

Input
There are several test cases. The first line of each case contains three integers, N, M and K. (1 <= N <= 100, 1 <= M <= 5000, 0 <= K <= 100). Then M lines followed, each contains four integers (u i, v i, a i, C i), indicating there is a directed road from city u i to v i, whose coefficient is a i and upper bound is C i. (1 <= u i, v i <= N, 0 < a i <= 100, C i <= 5)
 

 

Output
Output one line for each test case, indicating the minimum cost. If it is impossible to transport all the K units of goods, output -1.

 

 

Sample Input
2 1 2 1 2 1 2 2 1 2 1 2 1 1 2 2 2 1 2 1 2 1 2 2 2
 

 

Sample Output
4 -1 3

 

这题的重点是拆边,虽然之前没见过拆边的题目,但是这提这么简单的思路我竟然没想到,还是该给自己一个大耳光
 
  1 #include<iostream>

  2 #include<cstdio>

  3 #include<queue>

  4 #include<cstring>

  5 #include<climits>

  6 #define MAXP 110

  7 #define MAXE 51000

  8 using namespace std;

  9 struct Edge

 10 {

 11     int s,t,f,c,next;

 12 } edge[MAXE];

 13 int head[MAXP];

 14 int pre[MAXP];

 15 int dist[MAXP];

 16 bool isq[MAXP];

 17 int n,m,k,s,t,u,v,c,f,ent;

 18 void add(int S,int T,int f,int c)

 19 {

 20     edge[ent].s=S;

 21     edge[ent].t=T;

 22     edge[ent].f=f;

 23     edge[ent].c=c;

 24     edge[ent].next=head[S];

 25     head[S]=ent++;

 26     edge[ent].s=T;

 27     edge[ent].t=S;

 28     edge[ent].f=0;

 29     edge[ent].c=-c;

 30     edge[ent].next=head[T];

 31     head[T]=ent++;

 32 }

 33 int MIN(int a,int b)

 34 {

 35     return a<b?a:b;

 36 }

 37 bool spfa()

 38 {

 39     memset(pre,-1,sizeof(pre));//初始化路径为-1

 40     for(int i=s; i<=t; i++)

 41     {

 42         isq[i]=false;//每点开始时均不在队列里面

 43         dist[i]=INT_MAX;//初始化到每点的最小费用均为INT_MAX

 44     }

 45     queue<int>q;

 46     q.push(s);

 47     isq[s]=true;//源点s已经放入到队列里面去了

 48     dist[s]=0;//从源点到源点的距离为0

 49     while(!q.empty())//当队列为空时优化过程结束,退出循环

 50     {

 51         int temp1=q.front();

 52         q.pop();

 53         isq[temp1]=false;//该点已经退出队列

 54         for(int i=head[temp1]; i!=-1; i=edge[i].next) //从该点找通过邻接表找所有的以该点为起点的边,从中找出能优化的点

 55         {

 56             int temp2=edge[i].t;

 57             if(edge[i].f&&dist[temp2]>dist[temp1]+edge[i].c)

 58             {

 59                 dist[temp2]=dist[temp1]+edge[i].c;

 60                 pre[temp2]=i;

 61                 if(!isq[temp2])//如果该点不在队列中,则将该点放入队列中

 62                 {

 63                     q.push(temp2);

 64                     isq[temp2]=true;

 65                 }

 66             }

 67         }

 68     }

 69     return pre[t]!=-1;//如果pre[t]==-1的话说明没有找到从s到t的路径,即已经找到所有的路径了,结束循环

 70 }

 71 void mcmf()

 72 {

 73     int tot=0;

 74     int sum=0;

 75     int mincost=INT_MAX;

 76     int minn=INT_MAX;

 77     while(spfa())

 78     {

 79         tot++;

 80         mincost=dist[t];

 81         sum+=mincost;

 82         if(tot==k)

 83         {

 84             printf("%d\n",sum);

 85             return;

 86         }

 87         for(int i=pre[t];i!=-1;i=pre[i])//最小费用最大流中的减流的过程

 88         {

 89             edge[i].f--;

 90             edge[i^1].f++;

 91             i=edge[i].s;

 92         }

 93     }

 94     printf("-1\n");

 95 }

 96 int main()

 97 {

 98     while(~scanf("%d%d%d",&n,&m,&k))

 99     {

100         ent=0;

101         memset(head,-1,sizeof(head));

102         s=1;t=n;

103         for(int i=1;i<=m;i++)

104         {

105             scanf("%d%d%d%d",&u,&v,&c,&f);

106             for(int j=1;j<=f;j++)

107                 add(u,v,1,(j*2-1)*c);

108         }

109         if(m==0||n==1)

110         {

111             printf("0\n");

112             continue;

113         }

114         mcmf();

115     }

116     return 0;

117 }
View Code

 

你可能感兴趣的:(HDU)