【2017 United Kingdom and Ireland Programming Contest (UKIEPC 2017)】Knightsbridge Rises【最大流+路径输出】
题意:
给出nnn个起重机,每个起重机有两个属性,W[i]W[i]W[i]表示这个起重机的重量,L[i]L[i]L[i]表示这个起重机能够拉起的最大重量(可以拉重物也可以拉起重机)。现在有mmm栋楼以及mmm个重物,要求给出每栋楼起重机的分配方案,使得每栋楼最后留下的起重机可以拉起对应的重物。(1≤n≤100,1≤M≤100)(1\leq n\leq 100, 1\leq M\leq 100)(1≤n≤100,1≤M≤100)
思路:
比赛的时候以为所有的起重机都得用上…然后就想到了费用流…然后就是wawawawa\ wa\ wawa wa wa…其实这是一道比较简单的最大流问题,主要难点应该在路径输出。
我们先来考虑下如何建图。首先对于nnn个起重机进行拆点,拆点的目的是化边权为点权来限制流量。然后将源点sss和所有W[i]=0W[i]=0W[i]=0的点的入点相连,流量为111。每个拆开的点的入点和出点连一条流量为111的边。对于点xxx的出点与点yyy的入点,xxx与yyy相连(流量为111),当且仅当W[y]≤L[x]W[y]\leq L[x]W[y]≤L[x]。
再将mmm个重物与汇点相连,流量为111。最后对于每个重物,将所有L[i]L[i]L[i]大于重物重量的点与重物相连,流量为111。然后直接跑最大流即可。如果最大流为mmm,则输出路径,如果小于m,则输出impossibleimpossibleimpossible。
最后考虑本题最关键的步骤,求出最大流之后如何输出路径。
对于mmm个点,通过反向边往回跑,仅当反向边流量不为000,而正向边流量为000时才走这条边,跑到源点即停止,进行mmm遍dfsdfsdfs即可。
总结:
对于最大流的路径输出需要具体情况具体分析,但总体思想就是只跑反向边,并且是满流量的反向边。
但是可能会遇到dfsdfsdfs重复走某一节点的情况,需要在dfsdfsdfs时对于具体情况进行路径控制。
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#define rep(i,a,b) for(int i = a;i <= b;i++)
#define LOG1(x1,x2) cout << x1 << ": " << x2 << endl;
#define LOG2(x1,x2,y1,y2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << endl;
#define LOG3(x1,x2,y1,y2,z1,z2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << " , " << z1 << ": " << z2 << endl;
using namespace std;
const int inf = 1<<29,N = 1000,M = 1e5; //处理1e4-1e5规模的网络struct Edge{ int to,next,v,f;
}e[M];
int n,m,s,t; //顶点个数 边数 源点 汇点
int head[N],tot,dis[N],L[N],W[N],T[N];
queue<int> q;
vector<int> ans[N];void init() //千万别忘了初始化!
{tot = 1; memset(head,0,sizeof head); //点的编号是2~n,因为2^1 = 3, 3^1 = 2; 符合后续代码的操作
}void add(int x,int y,int v)
{e[++tot].to = y; e[tot].next = head[x]; e[tot].v = v; head[x] = tot; e[tot].f = 1;e[++tot].to = x; e[tot].next = head[y]; e[tot].v = 0; head[y] = tot; e[tot].f = -1; //反向边与正向边的流量之和为v
}bool bfs() //判断是否有增广路径
{memset(dis,0,sizeof dis);while(!q.empty()) q.pop();q.push(s); dis[s] = 1;while(!q.empty()){int x = q.front(); q.pop();for(int i = head[x];i;i = e[i].next){if(e[i].v && !dis[e[i].to]){q.push(e[i].to);dis[e[i].to] = dis[x]+1;if(e[i].to == t) return 1; //找到一条路就return }}}return 0;
}int dinic(int x,int flow) //dfs找增广路, 找到一条路, 就把增广的流量加到答案中
{ if(x == t) return flow;int rest = flow,k; //rest为输入的流量 for(int i = head[x];i && rest; i = e[i].next){if(e[i].v && dis[e[i].to] == dis[x]+1){k = dinic(e[i].to,min(rest,e[i].v));if(!k) dis[e[i].to] = 0; //剪枝,去掉增广完毕的点 e[i].v -= k;e[i^1].v += k; //反向边加上flow,相当于我们可以反悔从这条路流过 rest -= k; //k为能够被送出去的流量 }}return flow-rest; //总共被送出去了多少流量
}int solve()
{int flow = 0,maxflow = 0;while(bfs())while((flow = dinic(s,inf))) maxflow += flow; //while 循环内容 —— 判断是否还有增广路return maxflow;
}void dfs(int x,int flag){ //路径输出if(1 < x && x <= 1+n) ans[flag].push_back(x-1);if(x == s) return;for(int i = head[x]; i; i = e[i].next)if(e[i^1].v == 0 && e[i].to <= 1+2*n && e[i].f == -1) dfs(e[i].to,flag);
}int main()
{scanf("%d",&n); tot = 1;rep(i,1,n) scanf("%d%d",&W[i],&L[i]);scanf("%d",&m);rep(i,1,m) scanf("%d",&T[i]);s = 1, t = 2+2*n+m;rep(i,1,m) add(1+2*n+i,t,1);rep(i,1,n) if(W[i] == 0) add(s,i+1,1);rep(i,1,n) add(i+1,1+n+i,1);rep(i,1,n)rep(j,1,n)if(i != j && L[i] >= W[j]) add(i+1+n,1+j,1);rep(i,1,m)rep(j,1,n)if(L[j] >= T[i]) add(1+n+j,1+2*n+i,1);int maxflow = solve();if(maxflow != m) printf("impossible\n");else{rep(i,1,m)dfs(1+2*n+i,i);rep(i,1,m){for(int j = ans[i].size()-1; j >= 0; j--){printf("%d",ans[i][j]);if(j == 0) printf("\n");else printf(" ");}}}return 0;
} /*常见错误:
1.没有初始化【调了3h bug!】【微笑脸】2.不要怀疑模板!【她已经帮你A掉很多题目了】【值得你的信任】
*/
【2017 United Kingdom and Ireland Programming Contest (UKIEPC 2017)】Knightsbridge Rises【最大流+路径输出】相关推荐
- (寒假开黑gym)2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017)
layout: post title: (寒假开黑gym)2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017) au ...
- 2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017)
D.Distinctive Character 看到样例,第一个反应贪心.先写了个按这一位1和0的数目多少,确定0还是1的东西.感觉不够真,又写了个尽量加到相似的比较小的串上的贪心.在和前边的那个组合 ...
- 2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017)
A Drawing Borders 很多构造方法,下图可能是最简单的了 代码: #include<bits/stdc++.h> using namespace std; const int ...
- 2017-2018 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2017) G: Cordon Bleu
Cordon Bleu 时间限制: 1 Sec 内存限制: 128 MB 提交: 22 解决: 7 [提交][状态][讨论版][命题人:admin] 题目描述 A Parisian entrepr ...
- HYNB Contest 7:2017 Asia HCMC Vietnam National Programming Contest
A. Another Query on Array Problem B. Board Covering C. Cumulative Sums 题意 \(A_1=1,A_i=A_{i-1}+sod(A_ ...
- Nordic Collegiate Programming Contest 2017 题解
前几天打了一场外国人的比赛,感觉那边的题目质量还是很好的,区分度很鲜明,题目没有国内的难,坑点比较少,比较注重思维,基础算法. B题: Best Relay Team Picture by Ferna ...
- Sichuan University Programming Contest 2018 Preliminary
嗯为了防止大家AK,所以这次的A题和K题我们就当做不存在好了! 经历了昨天写了两个多小时的博客没保存的心态炸裂,今天终于下了个Markdown.所以我猜这篇的格式应该会更好看一点! 好吧废话不多说 题 ...
- 2019 China Collegiate Programming Contest Qinhuangdao Onsite F. Forest Program
2019 China Collegiate Programming Contest Qinhuangdao Onsite F. Forest Program 题目链接 The kingdom of Z ...
- 2017 ACM ICPC Asia Shenyang Regional Contest 题解(10 / 13)【每日亿题2 / 16】
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 A.(2017 ICPC shenyang I)Little Boxes B.(2017 ICP ...
- 2015 HIAST Collegiate Programming Contest J
Polygons Intersection 题意:给2个凸多边形,求相交面积 思路:不会,套板子就是了 AC代码: #include "iostream" #include &qu ...
最新文章
- 机器学习中的数学:一份新鲜出炉的热门草稿
- php矢量图图标,矢量图(字体图标)
- MongoDB:mongodb在项目开发时的安全验证、分页查询操作
- k8s控制器模式介绍
- wxWidgets:wxAuiTabArt类用法
- 大话数据结构16:图
- (组合数学笔记)拆分数各类定义及公式总结
- [转载] python中import问题
- python os模块进程管理
- windows权限了解
- 南航理论计算机科学答案,专业认证理念下的计算机专业本科生培养管理模式研究——以南航计算机科学与技术专业为例...
- 海思HI35xx平台软件开发快速入门之H265解码实例
- Struts2 教程
- linux nfs共享目录访问速度慢,linux之间共享文件夹选nfs还是选samba--
- Ubuntu下查看文件、文件夹和磁盘空间的大小
- 记录你生活的点滴,体会分享的快乐
- 矩阵中的旋转(Rotation)
- USB转串口驱动分析(一)
- 揭示未来方向:2018中国TMT行业“领秀榜”盛典直击
- 浅谈 Linux 内核开发之网络设备驱动[转]
热门文章
- 关于VMware的Server版卸载须知
- python中time模块time函数怎么写的_Python的time模块中的常用方法整理
- wordpress上传文件自动更名为时间形式
- pip安装tensorflow_Tensorflow源代码编译踩坑若干
- 性能计数器驱动_Vulkan 探密:AMD Vulkan 开源驱动源码解析-零
- nyoj 949哈利波特(细节题)
- 【UVA10256】The Great Divide(凸包相离判定)
- mysql银行储蓄额度格式_mysql创建表用于银行储蓄系统
- oracle18cscott,Oracle 18c 数据库中scott用户不存在的解决方法
- matlab剪切板中内容清除,如何清空剪贴板内容?剪切板内容清理过程