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. BUPT复试专题—哈夫曼树(2010)

    https://www.nowcoder.com/practice/162753046d5f47c7aac01a5b2fcda155?tpId=67&tqId=29635&tPage= ...

  2. go使用时间作为种子生成随机数

    原文:http://blog.csdn.net/qq_15437667/article/details/50851159 --------------------------------------- ...

  3. python各种类型转换

    python各种类型转换 学习了:https://blog.csdn.net/shanliangliuxing/article/details/7920400 https://blog.csdn.ne ...

  4. python发声

    python发声 学习了:http://www.jb51.net/article/62644.htm import winsound winsound.Beep(600,1000) #其中600表示声 ...

  5. 《C++ Primer Plus》学习笔记9

    <C++ Primer Plus>学习笔记9 第15章 友元.异常和其他 <<<<<<<<<<<<<<& ...

  6. iOS类的合理设计,面向对象思想

    每天更新的东西可能有反复的内容.当时每一部分的知识点是不同的,须要大家认真阅读 这里介绍了iOS类的合理设计.面向对象思想 main.m #import <Foundation/Foundati ...

  7. 图片3d轮放查看效果(V2.0):使用鼠标拖动实现图片的轮放

    上面的版本号为通过左右button实现图片轮放,这个版本号.是通过在窗体拖动鼠标.左右滑动图片. 关键点在于选择一个合适的值.使鼠标拖动时.全部图片均可显示,可是不会滑动过快或离开窗体. 不多说,直接 ...

  8. 如何给老婆解释什么是RESTful

    如何给老婆解释什么是RESTful Javdroider Hong 知乎专栏<Beautiful Java>的作者,一个热爱足球和健身的上进boy 1,543 人赞了该文章 老婆经常喜欢翻 ...

  9. 创建节点createElement

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...

  10. excel 创建数据有效性及背景颜色

    需求:用excel做数据或者表格时经常需要在一列中给出固定的几个进行悬着,这是如果每次键盘输入降低工作效率.如果做成鼠标双击进行选择,则提高很多效率,比如需要给一列填写Pass或Failure时,具体 ...