LA 2957 最大流,最短时间,输出路径
题意:n个星球,用最短的时间把k个超级计算机从s运到t;
其中,每个隧道是双向的,一个隧道里面只能有一个飞船在使用,一个飞船上只有一台计算机。
分析:
一个隧道只能给一个飞船用,那么假设需要t天,那么可以这样建图:
u结点,拆成t+1个,分别是 u0,u1,u2,...,ut;
u0是u的初始状态,ui是u在第i天的状态,那么建图就是:
a结点到b结点,ai 到 bi+1 一条容量为1的边,bi 到 ai+1 的容量为1的一条边。
对于每个结点,都有ui到ui+1 的容量是无穷大,因为可以停留。
一天一天增加结点,终点也发生变化,流量直到为k,就结束了。
然后输出路径:
遍历原图的上的每一条边,注意edges是残余网络,idx+=2;这才加了一条边。
问题问的路径是(A,B)编号为A的飞机,到达行星 B,行星B就是有流量的那一条边都后面那个结点。那么,编号A怎么求呢?
可以遍历一下这k个飞机,如果 j 所在的位置location[j] = a[i] 的话,就ok了。
#include <bits/stdc++.h> using namespace std; const int maxn = +;
const int INF = 0x3f3f3f3f; struct Edge{
int from,to,cap,flow;
}; bool operator < (const Edge& a,const Edge& b) {
return a.from < b.from||(a.from==b.from&&a.to<b.to);
} struct Dinic {
int n,m,s,t;
vector<Edge> edges;
vector<int> G[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn]; void init() {
edges.clear();
} void clearNodes(int a,int b) {
for(int i=a;i<=b;i++)
G[i].clear();
} void AddEdge(int from,int to,int cap) {
edges.push_back((Edge){from,to,cap,});
edges.push_back((Edge){to,from,,});
m = edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
} bool BFS() {
memset(vis,,sizeof(vis));
queue<int> Q;
Q.push(s);
vis[s] = ;
d[s] = ;
while(!Q.empty()) {
int x = Q.front(); Q.pop();
for(int i=;i<G[x].size();i++) {
Edge& e = edges[G[x][i]];
if(!vis[e.to]&&e.cap>e.flow) {
vis[e.to] = ;
d[e.to] = d[x] + ;
Q.push(e.to);
}
}
}
return vis[t];
} int DFS(int x,int a) {
if(x==t||a==) return a;
int flow = ,f;
for(int& i=cur[x];i<G[x].size();i++) {
Edge& e = edges[G[x][i]];
if(d[x]+==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>) {
e.flow +=f;
edges[G[x][i]^].flow-=f;
flow+=f;
a-=f;
if(a==) break;
}
}
return flow;
} int Maxflow(int s,int t,int limit) {
this->s = s;
this->t = t;
int flow = ;
while(BFS()) {
memset(cur,,sizeof(cur));
flow +=DFS(s,limit-flow);
if(flow==limit) break;
}
return flow;
}
}; Dinic g; int main()
{
int n,m,k,s,t;
int u[maxn],v[maxn]; while(~scanf("%d%d%d%d%d",&n,&m,&k,&s,&t)) {
for(int i=;i<m;i++) {
scanf("%d%d",&u[i],&v[i]);
}
g.init();
int day = ;
g.clearNodes(,n-);
int flow = ;
for(;;) {
g.clearNodes(day*n,day*n+n-);
for(int i=;i<n;i++)
g.AddEdge((day-)*n+i,day*n+i,INF);
for(int i=;i<m;i++) {
g.AddEdge((day-)*n+u[i]-,day*n+v[i]-,);
g.AddEdge((day-)*n+v[i]-,day*n+u[i]-,);
}
flow+=g.Maxflow(s-,day*n+t-,k-flow);
if(flow==k) break;
day++;
} printf("%d\n",day); int idx = ;
vector<int> location(k,s); for(int d=;d<=day;d++) {
idx +=n*;
vector<int> moved(k,);
vector<int> a,b; for(int i=;i<m;i++) {
int f1 = g.edges[idx].flow; idx+=;
int f2 = g.edges[idx].flow; idx+=;
if(f1==&&f2==) {
a.push_back(u[i]);
b.push_back(v[i]);
}
if(f1==&&f2==) {
a.push_back(v[i]);
b.push_back(u[i]);
}
} printf("%d",a.size());
for(int i=;i<a.size();i++) {
for(int j=;j<k;j++) { //找到具体是哪一个飞船
if(!moved[j]&&location[j]==a[i]) {
printf(" %d %d",j+,b[i]);
moved[j] = ;
location[j] = b[i];
break;
}
}
}
printf("\n"); } } return ;
}
LA 2957 最大流,最短时间,输出路径的更多相关文章
- PTA 紧急救援 /// dijkstra 最短路数 输出路径
题目大意: 给定 n m s t :表示n个点编号为0~n-1 m条边 起点s终点t 接下来一行给定n个数:表示第i个点的救援队数量 接下来m行给定u v w:表示点u到点v有一条长度为w的边 求从s ...
- POJ-3436(网络流+最大流+输出路径)
ACM Computer Factory POJ-3436 题目就是一个工厂n个加工机器,每个机器有一个效率w,q个材料入口,q个材料出口,每个口有三个数表示状态,1表示一定有入/出的材料,0表示没有 ...
- POJ 3684 Priest John's Busiest Day 2-SAT+输出路径
强连通算法推断是否满足2-sat,然后反向建图,拓扑排序+染色. 一种选择是从 起点開始,还有一种是终点-持续时间那个点 開始. 若2个婚礼的某2种时间线段相交,则有矛盾,建边. easy出错的地方就 ...
- UVA-624 CD---01背包+输出路径
题目链接: https://vjudge.net/problem/UVA-624 题目大意: 这道题给定一个时间上限,然后一个数字N,后面跟着N首歌的时间长度,要我们 求在规定时间w内每首歌都要完整的 ...
- Expm 10_2 实现Ford-Fulkerson算法,求出给定图中从源点s到汇点t的最大流,并输出最小割。
package org.xiu68.exp.exp10; import java.util.ArrayDeque; import java.util.ArrayList; import java.ut ...
- UVA 624 CD[【01背包】(输出路径)
<题目链接> 题目大意: 你要录制时间为N的带子,给你一张CD的不同时长的轨道,求总和不大于N的录制顺序 解题分析: 01背包问题,需要注意的是如何将路径输出. 由于dp时是会不断的将前面 ...
- hdu 1026(BFS+输出路径) 我要和怪兽决斗
http://acm.hdu.edu.cn/showproblem.php?pid=1026 模拟一个人走迷宫,起点在(0,0)位置,遇到怪兽要和他决斗,决斗时间为那个格子的数字,就是走一个格子花费时 ...
- 动态规划之DP中判断是否到达某一状态(最短时间是什么)?
codevs1684 垃圾陷阱 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 卡门——农夫约翰极其珍视的一条Holste ...
- IO流——递归(输出所有文件)
package pers.zbb.File; import java.io.File; public class FileDemo { public static void main(String[] ...
随机推荐
- spring bean name生成规则
现象: PVService PVServiceImpl ===>名称就是PVServiceImpl, 首字母没有小写 PageViewServiceImpl ==>名称是pageViewS ...
- 分布式事务框架-fescar
https://github.com/alibaba/fescar/wiki/%E6%A6%82%E8%A7%88?spm=5176.11156381.0.0.b9f85ceegUXvCC
- 结合element-ui表格自动生成sku规格列表
最近在写一个根据输入的规格,属性值动态生成sku表格,实现的效果大致如图,这是在vue项目里,结合element-UI表格写的,写好了就整理了一下,把代码贴上来,方便以后使用,不过代码里还是有一些重复 ...
- gitlab 的安装、汉化、卸载
新机 dell服务器 2核4G 官网: https://about.gitlab.com/install/ 1.本次安装选择版本v10.8.4 wget https://mirrors.tuna.ts ...
- 自定义element-ui主题
自定义element主题颜色:主要参考这个文章https://blog.csdn.net/wangcuiling_123/article/details/78513245,再自己做了一遍成功.感谢. ...
- Linux进程间通信的几种方式
1.管道及有名管道(pipe & named pipe) pipe 用于亲缘关系的进程间通信,named pipe除了pipe的功能外,还可以进行无亲缘关系进程间的通信. 2.信号(Signa ...
- java list分页
用list分页时会遇到一个问题:用户先选好页码,再传条件查询的时候,会导致查询的那一页有可能什么都没有.这时候我们给他当前查询的最后一页的内容会比较友好. int pageSize; //用户查询的每 ...
- 记录CentOS7.X版本下安装MySQL5.7数据库
记录CentOS7.X版本下安装MySQL5.7数据库 设置rpm下载目录在/opt目录下新建一个目录存放mysql cd /opt sudo mkdir mysql12 下载MySQL的源 wg ...
- cpp中memset函数的注意点
可参考: C++中memset函数的用法 C++中memset函数的用法 C++中memset()函数的用法详解 c/c++学习系列之memset()函数 透彻分析C/C++中memset函数 mem ...
- RTT设备与驱动之串口
有一般收发.中断方式.DMA方式: rt_device_t rt_device_find(const char* name); rt_err_t rt_device_open(rt_device_t ...