zoukankan      html  css  js  c++  java
  • 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 ai. If you want to carry x units of goods along this road, you should pay ai * x2 dollars to hire guards to protect your goods. And what’s worse, for each road i, there is an upper bound Ci, which means that you cannot transport more than Ci 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 (ui, vi, ai, Ci), indicating there is a directed road from city ui to vi, whose coefficient is ai and upper bound is Ci. (1 <= ui, vi <= N, 0 < ai <= 100, Ci <= 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
    ",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
    ");
     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
    ");
    112             continue;
    113         }
    114         mcmf();
    115     }
    116     return 0;
    117 }
    View Code
  • 相关阅读:
    《ucore lab1 exercise2》实验报告
    《ucore lab1 exercise1》实验报告
    《Tsinghua os mooc》第21~22讲 文件系统
    《Tsinghua os mooc》第17~20讲 同步互斥、信号量、管程、死锁
    《Tsinghua os mooc》第15~16讲 处理机调度
    《Tsinghua os mooc》第11~14讲 进程和线程
    《Tsinghua oc mooc》第8~10讲 虚拟内存管理
    bzoj3188 [Coci 2011]Upit(分块)
    P4514 上帝造题的七分钟(二维树状数组)
    bzoj3156 防御准备(斜率优化)
  • 原文地址:https://www.cnblogs.com/lthb/p/4466953.html
Copyright © 2011-2022 走看看