SCUT - 48 - 飞行员的配对方案 - 费用流
https://scut.online/p/48
一道二分图匹配,跑费用流就可以过了(其实最大流都可以了)。
#include<bits/stdc++.h>
#define MAXN_ 5050
#define INF 0x3f3f3f3f
#define P pair<int,int>
using namespace std;
struct edge {
int to,cap,cost,rev;
};
int n,m,flow,s,t,cap,res,cost,from,to,h[MAXN_];
std::vector<edge> G[MAXN_];
int dist[MAXN_],prevv[MAXN_],preve[MAXN_]; // 前驱节点和对应边
inline void add() {
G[from].push_back((edge) {
to,cap,cost,(int)G[to].size()
});
G[to].push_back((edge) {
from,,-cost,(int)G[from].size()-
});
} // 在vector 之中找到边的位置所在!
inline int read() {
int x=;
char c=getchar();
bool flag=;
while(c<''||c>'') {
if(c=='-')
flag=;
c=getchar();
}
while(c>=''&&c<='') {
x=(x<<)+(x<<)+c-'';
c=getchar();
}
return flag?-x:x;
}
inline void min_cost_flow(int s,int t,int f) {
fill(h+,h++n,);
while(f > ) {
priority_queue<P,vector<P>, greater<P> > D;
memset(dist,INF,sizeof dist);
dist[s] = ;
D.push(P(,s));
while(!D.empty()) {
P now = D.top();
D.pop();
if(dist[now.second] < now.first)
continue;
int v = now.second;
for(int i=; i<(int)G[v].size(); ++i) {
edge &e = G[v][i];
if(e.cap > && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
prevv[e.to] = v;
preve[e.to] = i;
D.push(P(dist[e.to],e.to));
}
}
}
// 无法增广 , 就是找到了答案了!
if(dist[t] == INF)
break;
for(int i=; i<=n; ++i)
h[i] += dist[i];
int d = f;
for(int v = t; v != s; v = prevv[v])
d = min(d,G[prevv[v]][preve[v]].cap);
f -= d;
flow += d;
res += d * h[t];
for(int v=t; v!=s; v=prevv[v]) {
edge &e = G[prevv[v]][preve[v]];
e.cap -= d;
G[v][e.rev].cap += d;
}
}
}
int main() {
int n1,n;
scanf("%d",&n1);
scanf("%d",&n); //n = read();
//m = read();
//s = read();
//t = read();
s=;
t=n+;
while() {
from = read();
to = read();
if(from==-&&to==-)
break;
//cap = read();
//cost = read();
cap=;
cost=;
add();
} for(int i=;i<=n1;i++){
from=s;
to=i;
cap=;
cost=;
add();
} for(int i=n1+;i<=n;i++){
from=i;
to=t;
cap=;
cost=;
add();
}
min_cost_flow(s,t,INF);
//printf("%d %d\n",flow,res);
printf("%d\n",flow);
return ;
}
洛谷上的居然要求出是哪些边。
那就根据自己丰富的编程经验瞎搞一发。
#include<bits/stdc++.h>
#define MAXN_ 5050
#define INF 0x3f3f3f3f
#define P pair<int,int>
using namespace std;
struct edge {
int to,cap,cost,rev;
};
int n,m,flow,s,t,cap,res,cost,from,to,h[MAXN_];
std::vector<edge> G[MAXN_];
int dist[MAXN_],prevv[MAXN_],preve[MAXN_]; // 前驱节点和对应边
inline void add() {
G[from].push_back((edge) {
to,cap,cost,(int)G[to].size()
});
G[to].push_back((edge) {
from,,-cost,(int)G[from].size()-
});
} // 在vector 之中找到边的位置所在!
inline int read() {
int x=;
char c=getchar();
bool flag=;
while(c<''||c>'') {
if(c=='-')
flag=;
c=getchar();
}
while(c>=''&&c<='') {
x=(x<<)+(x<<)+c-'';
c=getchar();
}
return flag?-x:x;
}
inline void min_cost_flow(int s,int t,int f) {
fill(h+,h++n,);
while(f > ) {
priority_queue<P,vector<P>, greater<P> > D;
memset(dist,INF,sizeof dist);
dist[s] = ;
D.push(P(,s));
while(!D.empty()) {
P now = D.top();
D.pop();
if(dist[now.second] < now.first)
continue;
int v = now.second;
for(int i=; i<(int)G[v].size(); ++i) {
edge &e = G[v][i];
if(e.cap > && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
prevv[e.to] = v;
preve[e.to] = i;
D.push(P(dist[e.to],e.to));
}
}
}
// 无法增广 , 就是找到了答案了!
if(dist[t] == INF)
break;
for(int i=; i<=n; ++i)
h[i] += dist[i];
int d = f;
for(int v = t; v != s; v = prevv[v])
d = min(d,G[prevv[v]][preve[v]].cap);
f -= d;
flow += d;
res += d * h[t];
for(int v=t; v!=s; v=prevv[v]) {
edge &e = G[prevv[v]][preve[v]];
e.cap -= d;
G[v][e.rev].cap += d;
}
}
}
int main() {
int n1,n;
/*1~n1 英国 n1~n 外国*/
scanf("%d",&n1);
scanf("%d",&n);
n+=n1; //n = read();
//m = read();
//s = read();
//t = read();
s=;
t=n+; int cnt=;
while() {
from = read();
to = read();
if(from==-&&to==-)
break;
//cap = read();
//cost = read();
/*手动设置容量和费用为1*/
cap=;
cost=;
add();
cnt+=;
} /*手动添加超级源点和超级汇点*/
for(int i=;i<=n1;i++){
from=s;
to=i;
cap=;
cost=;
add();
cnt+=;
} for(int i=n1+;i<=n;i++){
from=i;
to=t;
cap=;
cost=;
add();
cnt+=;
} vector<pair<int,int> >ans;
min_cost_flow(s,t,INF);
if(flow){
for(int i=;i<=n1;i++){
for(auto j:G[i]){
if(j.to!=s&&j.cap==){
ans.push_back({i,j.to});
}
}
} printf("%d\n",ans.size());
for(auto i:ans){
printf("%d %d\n",i.first,i.second);
}
}
else{
printf("No Solution!\n");
} return ;
}
SCUT - 48 - 飞行员的配对方案 - 费用流的更多相关文章
- 【bzoj4514】: [Sdoi2016]数字配对 图论-费用流
[bzoj4514]: [Sdoi2016]数字配对 好像正常的做法是建二分图? 我的是拆点然后 S->i cap=b[i] cost=0 i'->T cap=b[i] cost=0 然后 ...
- bzoj4514: [Sdoi2016]数字配对(费用流)
传送门 ps:费用流增广的时候费用和流量打反了……调了一个多小时 每个数只能参与一次配对,那么这就是一个匹配嘛 我们先把每个数分解质因数,记质因子总个数为$cnt_i$,那如果$a_i/a_j$是质数 ...
- 【BZOJ4514】数字配对(费用流)
题意: 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci× ...
- [SDOI2016]数字配对(费用流+贪心+trick)
重点是如何找到可以配对的\(a[i]\)和\(a[j]\). 把\(a[i]\)分解质因数.设\(a[i]\)分解出的质因数的数量为\(cnt[i]\). 设\(a[i]\geq a[j]\) 那么\ ...
- BZOJ4514 [Sdoi2016]数字配对 【费用流】
题目 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×c ...
- LuoguP2756 飞行员配对方案问题(最大流)
题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1名是外 ...
- [luogu P2756 ] 飞行员配对方案问题 (最大流)
强行做裸题做了两个小时..我果然太水了QAQ 题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 ...
- 【CJOJ1494】【洛谷2756】飞行员配对方案问题
题面 题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1 ...
- 网络流24题第一题(luogu2796飞行员配对方案)
飞行员配对方案 二分图裸题,可以拿最大流怼. 题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 ...
随机推荐
- spring-quartz定时任务使用小结
在实际项目中,通常须要用到定时任务(定时作业).spring框架提供了非常好的实现. 1. 下载spring-quartz插件包 这里默认当前系统中是集成了spring框架的基本功能的.去网上下载s ...
- BUPT复试专题—中位数(2014-2)
题目描述 给定一个长度为N的非降数列,求数列的中位数.中位数:当数列的项数N为奇数吋,处于中间位置的变最值即为中位数:当N 为偶数时,中位数则为处于中间位置的两个数的平均数. 输入 输入数据第一行 ...
- Andriod DiskLruCache的使用案例
DiskLruCache是谷歌推荐的用来实现硬盘缓存的类,本案例将对DiskLruCache的基本用法做一个总结,包括:创建缓存.查找使用缓存.移除缓存等等. 实现效果图 创建DiskLruCache ...
- 有关不同浏览器不同版本号的css以及js计算高度的问题
1.input在全部浏览器以及全部的版本号中,都是定义了高度.然后再定义padding或者border值.这时候都会撑开.高度是本身的高度在padding值和border值 2.select在gool ...
- Hadoop教程(一)
英文原文:cloudera,编译:ImportNew – Royce Wong Hadoop从这里开始!和我一起学习下使用Hadoop的基本知识,下文将以Hadoop Tutorial为主体带大家走一 ...
- Struts拦截器(转)
xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC &qu ...
- 设计模式入门之訪问者模式Visitor
//訪问者模式定义:表示一个作用于某对象结构中的各个元素的操作,它使你能够在不改变各元素类的前提下定义作用于这些元素的新操作. //从定义上看.这个模式跟装饰模式的定义非常类似(动态地给一个对象加入一 ...
- 2016-1-8 windows 7下安装mysql及其配置和运用
绪言 最近学习了一下mysql的相关用法,以及vs2010结合mysql的使用. 遇到的问题:1.安装mysql 5.6 绿色免安装版本,出现mysql server not connect loca ...
- 翻译:A Tutorial on the Device Tree (Zynq) -- Part II
A Tutorial on the Device Tree (Zynq) -- Part II 设备树结构 Zynq的设备树如下: /dts-v1/; / { #address-cells = < ...
- Android开发环境搭建时遇到问题的解决方法
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/linux_loajie/article/details/33823637 Android开发环境搭建 ...