hdu 4411 2012杭州赛区网络赛 最小费用最大流 ***
题意: 有 n+1 个城市编号 0..n,有 m 条无向边,在 0 城市有个警察总部,最多可以派出 k 个逮捕队伍,在1..n 每个城市有一个犯罪团伙,
每个逮捕队伍在每个城市可以选择抓或不抓,如果抓了 第 i 个城市的犯罪团伙,第 i-1 个城市的犯罪团伙就知道了消息 ,如果第 i-1 的犯罪
团伙之前没有被抓,任务就失败,问要抓到所有的犯罪团伙,派出的队伍需要走的最短路是多少。
分析: 最小费用最大流,需要注意的地方在于怎么去保证每个每个城市的团伙仅仅被抓一次,且在抓他之前,第i-1城市的团伙已经被抓。
方法是把拆点后的城市 i 和 i`之间的费用要设成一个很小的负值,这样可以保证该城市一定可以被访问到,
还有一点要注意的是派出的k个队可能有些队是不执行任务的,
方法是在 0 节点和 汇点之间连一条费用为0,容量为k的边
具体建图:
源点 s=2*n+1,
汇点 t=2*n+2,
每个城市拆成两个点 i 和 i+n,费用为 -100000,容量为 1
在源点和 0 之间连一条费用为 0 容量为 k 的边
在 0 和 城市 1..n之间连一条费用为 0 到 i 最短路容量为 1 的边(表示出发)
在 城市 n+1..n+n到汇点之间连一条费用为 0 到 i 最短路容量为 1 的边(表示回到总部)
在 城市 n+i..n+n 和 j(j>i)直间连一条费用为城市 i 到 j 最短路距离容量为 1 的边
求最小费用流。
- #include<cstdio>
- #include<iostream>
- #include<algorithm>
- #include<cstring>
- #include<cmath>
- #include<queue>
- #include<map>
- using namespace std;
- #define MOD 1000000007
- const int INF=0x3f3f3f3f;
- const double eps=1e-;
- typedef long long ll;
- #define cl(a) memset(a,0,sizeof(a))
- #define ts printf("*****\n");
- int n,m,tt;
- /*最小费用大流,求只需要取相反数结果即可。
- 点的总数为 N,点的编号 0~N -1*/
- const int MAXN = ;
- const int MAXM = ;
- struct Edge
- {
- int to,next,cap,flow,cost;
- }edge[MAXM];
- int head[MAXN],tol;
- int pre[MAXN],dis[MAXN];
- bool vis[MAXN];
- int N;//节点总个数,节点编号从0~N-1
- void init(int n)
- {
- N = n;
- tol = ;
- memset(head,-,sizeof(head));
- }
- void addedge(int u,int v,int cap,int cost)
- {
- edge[tol].to = v;
- edge[tol].cap = cap;
- edge[tol].cost = cost;
- edge[tol].flow = ;
- edge[tol].next = head[u];
- head[u] = tol++;
- edge[tol].to = u;
- edge[tol].cap = ;
- edge[tol].cost = -cost;
- edge[tol].flow = ;
- edge[tol].next = head[v];
- head[v] = tol++;
- }
- bool spfa(int s,int t)
- {
- queue<int>q;
- for(int i = ;i < N;i++)
- {
- dis[i] = INF;
- vis[i] = false;
- pre[i] = -;
- }
- dis[s] = ;
- vis[s] = true;
- q.push(s);
- while(!q.empty())
- {
- int u = q.front();
- q.pop();
- vis[u] = false;
- for(int i = head[u]; i != -;i = edge[i].next)
- {
- int v = edge[i].to;
- if(edge[i].cap > edge[i].flow &&
- dis[v] > dis[u] + edge[i].cost )
- {
- dis[v] = dis[u] + edge[i].cost;
- pre[v] = i;
- if(!vis[v])
- {
- vis[v] = true;
- q.push(v);
- }
- }
- }
- }
- if(pre[t] == -)return false;
- else return true;
- }
- //返回的是最大流,cost存的是最小费用
- int minCostMaxflow(int s,int t)
- {
- int flow = ;
- int cost = ;
- while(spfa(s,t))
- {
- int Min = INF;
- for(int i = pre[t];i != -;i = pre[edge[i^].to])
- {
- if(Min > edge[i].cap - edge[i].flow)
- Min = edge[i].cap - edge[i].flow;
- }
- for(int i = pre[t];i != -;i = pre[edge[i^].to])
- {
- edge[i].flow += Min;
- edge[i^].flow -= Min;
- cost += edge[i].cost * Min;
- }
- flow += Min;
- }
- return cost;
- }
- int c[MAXN][MAXN];
- void floyd(){
- for(int k=;k<=n;++k){
- for(int i=;i<=n;++i){
- for(int j=;j<=n;++j){
- c[i][j]=min(c[i][j],c[i][k]+c[k][j]);
- }
- }
- }
- }
- int main()
- {
- int i,j,k,ca=;
- #ifndef ONLINE_JUDGE
- freopen("1.in","r",stdin);
- #endif
- while(~scanf("%d%d%d",&n,&m,&k)&&n&&m&&k)
- {
- init(*n+);
- for(i=;i<=n;i++)
- for(j=;j<=n;j++)
- {
- c[i][j]=(i==j)?:INF;
- }
- int st=*n+;
- int ed=*n+;
- addedge(st,,k,);
- addedge(,ed,k,);
- while(m--)
- {
- int u,v,w;
- scanf("%d%d%d",&u,&v,&w);
- c[u][v]=c[v][u]=min(c[u][v],w);
- }
- floyd();
- for(i=;i<=n;i++)
- {
- addedge(,i,,c[][i]);
- addedge(i,i+n,,-);
- addedge(i+n,ed,,c[][i]);
- }
- for(i=;i<=n;i++)
- {
- for(j=i+;j<=n;j++)
- {
- addedge(i+n,j,,c[i][j]);
- }
- }
- printf("%d\n",minCostMaxflow(st,ed)+*n);
- }
- }
hdu 4411 2012杭州赛区网络赛 最小费用最大流 ***的更多相关文章
- hdu 4412 2012杭州赛区网络赛 期望
虽然dp方程很好写,就是这个期望不知道怎么求,昨晚的BC也是 题目问题抽象之后为:在一个x坐标轴上有N个点,每个点上有一个概率值,可以修M个工作站, 求怎样安排这M个工作站的位置,使得这N个点都走到工 ...
- Our Journey of Dalian Ends 乌鲁木齐网络赛 最小费用最大流
Life is a journey, and the road we travel has twists and turns, which sometimes lead us to unexpecte ...
- hdu 4273 2012长春赛区网络赛 三维凸包中心到最近面距离 ***
新模板 /* HDU 4273 Rescue 给一个三维凸包,求重心到表面的最短距离 模板题:三维凸包+多边形重心+点面距离 */ #include<stdio.h> #include&l ...
- hdu 4741 2013杭州赛区网络赛 dfs ***
起点忘记录了,一直wa 代码写的很整齐,看着很爽 #include<cstdio> #include<iostream> #include<algorithm> # ...
- hdu 4739 2013杭州赛区网络赛 寻找平行坐标轴的四边形 **
是平行坐标轴的,排个序搞一下就行了,卧槽,水的不行 如果不是平行的,则需要按照边长来判断
- hdu 4738 2013杭州赛区网络赛 桥+重边+连通判断 ***
题意:有n座岛和m条桥,每条桥上有w个兵守着,现在要派不少于守桥的士兵数的人去炸桥,只能炸一条桥,使得这n座岛不连通,求最少要派多少人去. 处理重边 边在遍历的时候,第一个返回的一定是之前去的边,所以 ...
- hdu 4293 2012成都赛区网络赛 dp ****
题意:有n个人,可任意分成若干组,然后每个人个各提供一个信息,表示他们组前面有多少人,后面有多少人.问最多有多少个信息是不冲突的. 将n个人看成一组区间,然后每个人的信息可以表示为该人所在组的区间,然 ...
- hdu 4291 2012成都赛区网络赛 矩阵快速幂 ***
分析:假设g(g(g(n)))=g(x),x可能非常大,但是由于mod 10^9+7,所以可以求出x的循环节 求出x的循环节后,假设g(g(g(n)))=g(x)=g(g(y)),即x=g(y),y也 ...
- hdu 4278 2012天津赛区网络赛 数学 *
8进制转为10进制 #include<cstdio> #include<iostream> #include<algorithm> #include<cstr ...
随机推荐
- js里面的 InttoStr 和 StrtoInt
javascript 字符串 和 数字的转换,话说好灵活,感觉回不去pascal了 int转换string: 1,var str=String(int); 2,num.toString(param) ...
- MyBatis <if>标签的一些问题
1.常见错误: There is no getter for property named 'parentId' in 'class java.lang.Long'(或者String) org.myb ...
- VS2010调试速度很慢
1.使用vs2010,感觉速度越来越慢.重新设置了vs2010的环境(在vs2010命令提示符下,执行devenv.exe /resetuserdata),居然解决了这个问题,速度跑的很好.网上有人说 ...
- Windows下配置Java开发环境
学习Java第一步是配置本地开发环境,学习最基本的桌面开发,下面以win7为例配置Java开发环境,即:JDK+JRE+Eclipse,安装JDK的时候会默认安装JRE,根据提示安装就可以了. 首先去 ...
- XE 的程序升级 XE5 问题处理记录
XE 的程序升级 XE5 问题处理记录 1. [dcc32 Fatal Error] frxClass.pas(3556): F1026 File not found: 'xxxxx\Registr ...
- malloc原理和内存碎片
当一个进程发生缺页中断的时候,进程会陷入内核态,执行以下操作: 1.检查要访问的虚拟地址是否合法 2.查找/分配一个物理页 3.填充物理页内容(读取磁盘,或者直接置0,或者啥也不干) 4.建立映射关系 ...
- 前台js分页,自己手写逻辑2
//设置分页 var pageSize = 10; //设置一次显示多少页 var pageLimit = 5; $(function(){ $.post("rest/rtdbfix/lis ...
- Android Volley入门到精通:定制自己的Request
经过前面两篇文章的学习,我们已经掌握了Volley各种Request的使用方法,包括StringRequest.JsonRequest.ImageRequest等.其中StringRequest用于请 ...
- 【leetcode】Binary Search Tree Iterator(middle)
Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the ro ...
- 【网络】VPN和代理服务器的区别
来自:http://www.zhihujingxuan.com/19311.html [scotttony的回答(41票)]: VPN和ssh哪个比较好, 要看你怎么定义是“好”. ssh作为一个创建 ...