题意:

给出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【最大流+路径输出】相关推荐

  1. (寒假开黑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 ...

  2. 2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017)

    D.Distinctive Character 看到样例,第一个反应贪心.先写了个按这一位1和0的数目多少,确定0还是1的东西.感觉不够真,又写了个尽量加到相似的比较小的串上的贪心.在和前边的那个组合 ...

  3. 2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017)

    A Drawing Borders 很多构造方法,下图可能是最简单的了 代码: #include<bits/stdc++.h> using namespace std; const int ...

  4. 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 ...

  5. 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_ ...

  6. Nordic Collegiate Programming Contest 2017 题解

    前几天打了一场外国人的比赛,感觉那边的题目质量还是很好的,区分度很鲜明,题目没有国内的难,坑点比较少,比较注重思维,基础算法. B题: Best Relay Team Picture by Ferna ...

  7. Sichuan University Programming Contest 2018 Preliminary

    嗯为了防止大家AK,所以这次的A题和K题我们就当做不存在好了! 经历了昨天写了两个多小时的博客没保存的心态炸裂,今天终于下了个Markdown.所以我猜这篇的格式应该会更好看一点! 好吧废话不多说 题 ...

  8. 2019 China Collegiate Programming Contest Qinhuangdao Onsite F. Forest Program

    2019 China Collegiate Programming Contest Qinhuangdao Onsite F. Forest Program 题目链接 The kingdom of Z ...

  9. 2017 ACM ICPC Asia Shenyang Regional Contest 题解(10 / 13)【每日亿题2 / 16】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 A.(2017 ICPC shenyang I)Little Boxes B.(2017 ICP ...

  10. 2015 HIAST Collegiate Programming Contest J

    Polygons Intersection 题意:给2个凸多边形,求相交面积 思路:不会,套板子就是了 AC代码: #include "iostream" #include &qu ...

最新文章

  1. 机器学习中的数学:一份新鲜出炉的热门草稿
  2. php矢量图图标,矢量图(字体图标)
  3. MongoDB:mongodb在项目开发时的安全验证、分页查询操作
  4. k8s控制器模式介绍
  5. wxWidgets:wxAuiTabArt类用法
  6. 大话数据结构16:图
  7. (组合数学笔记)拆分数各类定义及公式总结
  8. [转载] python中import问题
  9. python os模块进程管理
  10. windows权限了解
  11. 南航理论计算机科学答案,专业认证理念下的计算机专业本科生培养管理模式研究——以南航计算机科学与技术专业为例...
  12. 海思HI35xx平台软件开发快速入门之H265解码实例
  13. Struts2 教程
  14. linux nfs共享目录访问速度慢,linux之间共享文件夹选nfs还是选samba--
  15. Ubuntu下查看文件、文件夹和磁盘空间的大小
  16. 记录你生活的点滴,体会分享的快乐
  17. 矩阵中的旋转(Rotation)
  18. USB转串口驱动分析(一)
  19. 揭示未来方向:2018中国TMT行业“领秀榜”盛典直击
  20. 浅谈 Linux 内核开发之网络设备驱动[转]

热门文章

  1. 关于VMware的Server版卸载须知
  2. python中time模块time函数怎么写的_Python的time模块中的常用方法整理
  3. wordpress上传文件自动更名为时间形式
  4. pip安装tensorflow_Tensorflow源代码编译踩坑若干
  5. 性能计数器驱动_Vulkan 探密:AMD Vulkan 开源驱动源码解析-零
  6. nyoj 949哈利波特(细节题)
  7. 【UVA10256】The Great Divide(凸包相离判定)
  8. mysql银行储蓄额度格式_mysql创建表用于银行储蓄系统
  9. oracle18cscott,Oracle 18c 数据库中scott用户不存在的解决方法
  10. matlab剪切板中内容清除,如何清空剪贴板内容?剪切板内容清理过程