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 - 飞行员的配对方案 - 费用流的更多相关文章

  1. 【bzoj4514】: [Sdoi2016]数字配对 图论-费用流

    [bzoj4514]: [Sdoi2016]数字配对 好像正常的做法是建二分图? 我的是拆点然后 S->i cap=b[i] cost=0 i'->T cap=b[i] cost=0 然后 ...

  2. bzoj4514: [Sdoi2016]数字配对(费用流)

    传送门 ps:费用流增广的时候费用和流量打反了……调了一个多小时 每个数只能参与一次配对,那么这就是一个匹配嘛 我们先把每个数分解质因数,记质因子总个数为$cnt_i$,那如果$a_i/a_j$是质数 ...

  3. 【BZOJ4514】数字配对(费用流)

    题意: 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci× ...

  4. [SDOI2016]数字配对(费用流+贪心+trick)

    重点是如何找到可以配对的\(a[i]\)和\(a[j]\). 把\(a[i]\)分解质因数.设\(a[i]\)分解出的质因数的数量为\(cnt[i]\). 设\(a[i]\geq a[j]\) 那么\ ...

  5. BZOJ4514 [Sdoi2016]数字配对 【费用流】

    题目 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×c ...

  6. LuoguP2756 飞行员配对方案问题(最大流)

    题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1名是外 ...

  7. [luogu P2756 ] 飞行员配对方案问题 (最大流)

    强行做裸题做了两个小时..我果然太水了QAQ 题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 ...

  8. 【CJOJ1494】【洛谷2756】飞行员配对方案问题

    题面 题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1 ...

  9. 网络流24题第一题(luogu2796飞行员配对方案)

    飞行员配对方案 二分图裸题,可以拿最大流怼. 题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 ...

随机推荐

  1. Linux/UNIX之文件和文件夹(2)

    文件和文件夹(2) link.ulink.remove和rename函数 #include <unistd.h> int link(const char *oldpath, const c ...

  2. HTML页面底部无用留白

    HTML页面底部无用留白,可以再footer样式中加入: overflow: hidden; 如有错误,请您指正~

  3. MVC上传文件并模拟进度条

    进度条样式和JS <style type="text/css"> .spa { font-size: 12px; color: #0066ff; } .put { fo ...

  4. LA4043 - Ants(二分图完备最佳匹配KM)

    option=com_onlinejudge&Itemid=8&page=show_problem&problem=2044">https://icpcarch ...

  5. CPU Stepping

    http://baike.baidu.com/view/16839.htm?fr=ala0_1_1 步进 编辑   步进(Stepping)是CPU的一个重要参数,也叫分级鉴别产品数据转换规范,“步进 ...

  6. Redis java使用

    直接应用redis.clients:jedis的jar包到项目中,然后直接就可以使用,具体对五种类型的数据操作方法,可以翻代码找到. 连接到 redis 服务 实例 import redis.clie ...

  7. sim的准确识别技术

    几个月钱,我换了一个手机,本着工科男动手能力强的原则,自己用✂️把sim卡剪成了一个小卡,然后成功的可以使用了. 然而就在昨天,我将卡拿出之后,再放回去,却无法识别我的sim卡了. 我上网查了方法,怀 ...

  8. Scaling with Microservices and Vertical Decomposition

    Scaling with Microservices and Vertical Decomposition – dev.otto.de https://dev.otto.de/2014/07/29/s ...

  9. leetcode 681. Next Closest Time

    Given a time represented in the format "HH:MM", form the next closest time by reusing the ...

  10. POJ2752 Seek the Name, Seek the Fame —— KMP next数组

    题目链接:https://vjudge.net/problem/POJ-2752 Seek the Name, Seek the Fame Time Limit: 2000MS   Memory Li ...