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

思路:很神奇的建图,参考大牛的:

如果人为添加t->s的边,那么图中所有顶点要满足的条件都是一样的了,我们以此为目的来建图。

对于每条边,我们只有两种操作,要么保留要么删除,那么先假设两种操作都能满足条件,我们就可以选择花费小的操作来执行,最后再根据实际情况调整。
首先不加入任何边,在添加或删除(不加入)边的过程中,对每个顶点v记录in[v]为其当前入度,out[v]为其出度,sum为当前的总花费。
那么对于每条边,如果a<=b,那么保留这条边,in[v]++,out[u]++,sum+=a,然后连边v->u,流量1,费用为b-a(如果删除这条边的费用)
如果b<a,那么删去这条边,sum+=b,然后连边u->v,流量1,费用为a-b(如果保留这条边的费用)。
然后我们人为的加入一条t->s,直接in[s]++,out[t]++,使得图中所有点处于相同的状况。
设立超级源汇S、T,对于原图的每个点i,如果in[i]>out[i],则连边S->i,流量为in[i]-out[i], 费用为0,否则连边i->T,流量为out[i]-in[i],费用为0。至此,建图完成。

现在求S到T的费用流mincost,然后检查从S发出的边,如果全部满流则有解,答案就是sum+mincost,否则无解。
这样建图的意义:例如对点i,in[i]>out[i],说明当前该点入度大于出度,那么我们把之前删除的以i为起点的边添加回来 或者把之前保留的以i为终点的边删除,现在边的费用其实是改变边状态所需要额外付的费用,而最小费用流所求的就是全部调整的总费用了,于是答案就是sum(初始操作的费用)+mincost(额外付出的费用)。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define MAXN 222
#define MAXM 2222222
#define inf 1<<30 struct Edge{
int v,cap,cost,next;
}edge[MAXM]; int n,m,vs,vt,NE;
int head[MAXN]; void Insert(int u,int v,int cap,int cost)
{
edge[NE].v=v;
edge[NE].cap=cap;
edge[NE].cost=cost;
edge[NE].next=head[u];
head[u]=NE++; edge[NE].v=u;
edge[NE].cap=;
edge[NE].cost=-cost;
edge[NE].next=head[v];
head[v]=NE++;
} int dist[MAXN],pre[MAXN],cur[MAXN];
bool mark[MAXN];
bool spfa(int vs,int vt)
{
memset(mark,false,sizeof(mark));
fill(dist,dist+MAXN-,inf);
dist[vs]=;
queue<int>que;
que.push(vs);
while(!que.empty()){
int u=que.front();
que.pop();
mark[u]=false;
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].v,cost=edge[i].cost;
if(edge[i].cap>&&dist[u]+cost<dist[v]){
dist[v]=cost+dist[u];
pre[v]=u;
cur[v]=i;
if(!mark[v]){
mark[v]=true;
que.push(v);
}
}
}
}
return dist[vt]<inf;
} int MinCostFlow(int vs,int vt)
{
int flow=,cost=;
while(spfa(vs,vt)){
int aug=inf;
for(int u=vt;u!=vs;u=pre[u]){
aug=min(aug,edge[cur[u]].cap);
}
flow+=aug;cost+=dist[vt]*aug;
for(int u=vt;u!=vs;u=pre[u]){
edge[cur[u]].cap-=aug;
edge[cur[u]^].cap+=aug;
}
}
return cost;
} int In[MAXN],Out[MAXN];
bool Judge()
{
for(int i=head[vs];i!=-;i=edge[i].next){
int cap=edge[i].cap;
if(cap>)return false;
}
return true;
} int main()
{
int s,t,u,v,a,b,sum,cost,T=,_case;
scanf("%d",&_case);
while(_case--){
scanf("%d%d%d%d",&n,&m,&s,&t);
NE=;
memset(head,-,sizeof(head));
memset(In,,sizeof(In));
memset(Out,,sizeof(Out));
sum=;
while(m--){
scanf("%d%d%d%d",&u,&v,&a,&b);
if(a<=b){
Insert(v,u,,b-a);
In[v]++,Out[u]++;
sum+=a;
}else {
Insert(u,v,,a-b);
sum+=b;
}
}
In[s]++;
Out[t]++;
vs=,vt=n+;
for(int i=;i<=n;i++){
if(In[i]>Out[i])Insert(vs,i,(In[i]-Out[i]),);
else if(In[i]<Out[i])Insert(i,vt,(Out[i]-In[i]),);
}
cost=MinCostFlow(vs,vt);
printf("Case %d: ",T++);
if(Judge()){
printf("%d\n",sum+cost);
}else
puts("impossible");
}
return ;
}

hdu 4067(最小费用最大流)的更多相关文章

  1. 【网络流#2】hdu 1533 - 最小费用最大流模板题

    最小费用最大流,即MCMF(Minimum Cost Maximum Flow)问题 嗯~第一次写费用流题... 这道就是费用流的模板题,找不到更裸的题了 建图:每个m(Man)作为源点,每个H(Ho ...

  2. hdu 1533(最小费用最大流)

    Going Home Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  3. hdu 4862KM&最小费用最大流

    /*最小K路径覆盖的模型,用费用流或者KM算法解决, 构造二部图,X部有N*M个节点,源点向X部每个节点连一条边, 流量1,费用0,Y部有N*M个节点,每个节点向汇点连一条边,流量1, 费用0,如果X ...

  4. HDU 1533 最小费用最大流(模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=1533 这道题直接用了模板 题意:要构建一个二分图,家对应人,连线的权值就是最短距离,求最小费用 要注意void ...

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

    Transportation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  6. hdu 6437 /// 最小费用最大流 负花费 SPFA模板

    题目大意: 给定n,m,K,W 表示n个小时 m场电影(分为类型A.B) K个人 若某个人连续看了两场相同类型的电影则失去W 电影时间不能重叠 接下来给定m场电影的 s t w op 表示电影的 开始 ...

  7. hdu 2485(最小费用最大流)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2485 思路:题目的意思是删除最少的点使1,n的最短路大于k.将点转化为边,容量为1,费用为0,然后就是 ...

  8. hdu 6201(最小费用最大流)

    transaction transaction transaction Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 132768/1 ...

  9. hdu 2686 Matrix 最小费用最大流

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2686 Yifenfei very like play a number game in the n*n ...

随机推荐

  1. Java学习笔记1、常用dos命令

    cd 改变当前目录 sys      制作DOS系统盘 copy 拷贝文件 del 删除文件 deltree 删除目录树 dir 列文件名 diskcopy 制磁盘 edit 文本编辑 format ...

  2. winfrom cahce 问题

    .Clear()不能随便用 .Clear()的比较没有什么意思,因为只是把DataTable清空而已,在堆中任然分配内存,一般要比较也是比较Close()方法,不过DataTable没有这个方法 至于 ...

  3. C# 字符串数组转换为整形数组

    /// <summary> /// 字符串数组转换整形数组 /// </summary> /// <param name="Content">字 ...

  4. Caused by: java.lang.NoSuchMethodError: javax.persistence.JoinColumn.foreignKey()Ljavax/persistence/

    Caused by: Java.lang.NoSuchMethodError: javax.persistence.JoinColumn.foreignKey()Ljavax/persistence/ ...

  5. excel合并单元格

    最简单的: =A1&B1&C1 在C14单元格中输入公式:=CONCATENATE(A14,"@",B14,".com"),确认后,即可将A14 ...

  6. 常用排序算法及Java实现

    概述 在计算器科学与数学中,一个排序算法(英语:Sorting algorithm)是一种能将一串数据依照特定排序方式进行排列的一种算法.本文将总结几类常用的排序算法,包括冒泡排序.选择排序.插入排序 ...

  7. Jumpserver web界面跳板机

    Jumpserver.org 普通用户 仪表盘 查看主机 上传下载 访问官网 欢迎使用Jumpserver开源跳板机系统 帮助 Log out 查看资产 仪表盘 资产管理 查看资产 主机详细信息列表 ...

  8. Bash中的括号(一)

    初学Bash脚本编程,里面的各种括号,绝对是一个大坑,为了救人救己,以防再度入坑,特记录如下: 一.单小括号: 1.创建子Shell.单个小括号用来创建一个子shell,子shell允许你在不影响当前 ...

  9. [容器]docker创建镜像

    手动创建: docker run -d -p mynginx:v2 nginx rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest- ...

  10. MEF教程

    http://www.cnblogs.com/content/archive/2013/05/31/3111156.html