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 ...
随机推荐
- linux 环境 php 链接 sqlserver 2008
说明 由于业务需要 在 linux 系统下的 PHP 环境中 要链接 sqlserver2008 数据库 . 添加PHP 链接数据库扩展 php-mssql dockerfile FROM hub.0 ...
- 提高系统性能——对SQL语句优化的思考
软件在研发的过程中自始至终都在留意着系统的可扩展性.但与此同一时候也在关注着系统的性能,SQL语句作为系统性能的一环不容忽视.从今天開始结合开发的经验,谈一下我对SQL语句优化的理解和认知: 1.在联 ...
- HDU 1284 钱币兑换问题 (完全背包)
钱币兑换问题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Subm ...
- postgres SQL编译过程
PG启动首先完成主进程和后台进程的启动,启动时完成数据库文件的打开,共享内存的建立等.接着,所有SQL都会启动1个单独的进程处理SQL的执行过程. 新的进程首先是进行自身的初始化,最主要的是初始化内存 ...
- 混合minxins
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- c++学习笔记之基础---类内声明函数后在类外定义的一种方法
在C++的“类”中经常遇到这样的函数, 返回值类型名 类名::函数成员名(参数表){ 函数体.} 双冒号的作用 ::域名解析符!返回值类型名 类名::函数成员名(参数表) { 函数体. } 这个是在类 ...
- 正则表达式pattern的匹配格式
0> 匹配 -------------------------------------------------------------------------------- (pattern) ...
- timestamp 转 date 处理后再转timestamp
package com.jmu.ccjoin.service.impl; import java.sql.Timestamp;import java.util.Calendar;import java ...
- Javascript中两种最通用的定义类的方法
在Javascript中,一切都是对象,包括函数.在Javascript中并没有真正的类,不能像C#,PHP等语言中用 class xxx来定义.但Javascript中提供了一种折中的方案:把对象定 ...
- javascript flash 弹框
1. [代码]FlashBox // JavaScript Documentfunction FlashBox(src,width,height){var docbody = document ...