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 ...
随机推荐
- Mecanim动画编辑器 - 加入动画层实现并行动作
1.创建新的状态层 a) 通过下图的1button创建一个新的层 b) 通过下图2属性设置图层的权重.假设为0,则该图层的状态不会影响到总的状态机 c) Mask是设置动画的Avatar的关联节 ...
- 杭电1863 畅通project
畅通project Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- OnlineJudge测试数据生成模板
int类型数据生成一(正数最多4位): #include <bits/stdc++.h> using namespace std; int main() { freopen("t ...
- TFTP服务器
为什么要学习有关TFTP服务器的安装及配置呢?主要是为了后续学习有关linux系统的无人值守安装做准备. TFTP简单文件传输协议,使用UDP的69端口.主要提供文件的上传和下载,TFTP一般是适用于 ...
- python—networkx:依据图的权重绘图
首先输入边和边的权重,随后画出节点位置.依据权重大小划分实边和虚边 #coding:utf-8 #!/usr/bin/env python """ An example ...
- zoj 3573 Under Attack(线段树 标记法 最大覆盖数)
Under Attack Time Limit: 10 Seconds Memory Limit: 65536 KB Doctor serves at a military air f ...
- font-family,font-size,color
CreateTime--2017年12月20日16:43:35 Author:Marydon css设置字体样式 1.font-family 语法:属性值可以有一个或多个,多个值之间使用逗号隔开. ...
- js 监控浏览器关闭(完美兼容chrome & ie & fire fox)
var UnloadConfirm = {}; UnloadConfirm.MSG_UNLOAD = "数据尚未保存,离开后可能会导致数据丢失\n\n您确定要离开吗?"; Unlo ...
- Posix消息队列相关函数
Posix消息队列(message queue) IPC函数中常用的参数取值: 打开或创建POSIX IPC对象所用的各种oflag常值o_RDONLY 只读O_WRONLY 只写O_RDWD ...
- ubuntu 系统启动时找不到根文件系统
报出的错误大概为: Alert! /dev/disk/by-uuid/ ....... does not exist 最后进入了 initramdiskfs 的命令行终端 . 输入 blkid 命令却 ...