线性规划与网络流24题 01飞行员分配方案问题
题意:
飞行员分为国外国内两种。国外飞行员只能和指定国内飞行员配对,问最佳配对方式使得配对对数最大。
思路:
跑最大流。
源码:
EK:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
#define inf (1000000000)
const int MAXN = 100 + 5;
int flow[MAXN][MAXN];
int org_flow[MAXN][MAXN];
int p[MAXN];
int n, m;
void init()
{
memset(flow, 0, sizeof(flow));
scanf("%d%d", &m, &n);
for(int i = 1 ; i <= m ; i++)
flow[0][i] = 1;
for(int i = m + 1 ; i <= n ; i++)
flow[i][n + 1] = 1;
int u, v;
for(;;){
scanf("%d%d", &u, &v);
if(u + v == -2)
break;
flow[u][v] = 1;
}
memcpy(org_flow, flow, sizeof(flow));
}
void check_flow()
{
printf("flow\n");
for(int i = 0 ; i <= n + 1 ; i++){
for(int j = 0 ; j <= n + 1 ; j++)
printf("%d ", flow[i][j]);
printf("\n");
}
printf("flow\n");
}
queue<int>que;
int vis[MAXN], a[MAXN];
int EK()
{
int ans = 0;
while(1){
while(!que.empty()) que.pop();
memset(a, 0, sizeof(a));
memset(vis, 0, sizeof(vis));
memset(p, 0, sizeof(p));
vis[0] = 1;
a[0] = inf;
p[0] = 0;
que.push(0);
// check_flow();
while(!que.empty()){
int org = que.front(); que.pop();
for(int i = 0 ; i <= n + 1; i++){
if(flow[org][i] && !vis[i]){
que.push(i);
a[i] = min(a[org], flow[org][i]);
vis[i] = 1;
p[i] = org;
}
}
}
// printf("p\n");
// for(int i = 0 ; i <= n + 1 ; i++)
// printf("%d ", p[i]);
// printf("\np\n");
if(a[n + 1] == 0)
break;
ans += a[n + 1];
int s = n + 1;
while(0 != s){
// printf("s = %d\n", s);
flow[p[s]][s] -= a[n + 1];
flow[s][p[s]] += a[n + 1];
s = p[s];
}
}
return ans;
}
int main()
{
freopen("air10.in", "r", stdin);
init();
printf("%d\n", EK());
for(int i = 1 ; i <= m ; i++){
for(int j = m + 1 ; j <= n ; j++)
if(flow[i][j] != org_flow[i][j])
printf("%d %d\n", i, j);
}
return 0;
}
Dinic:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define inf (1000000000)
const int MAXN = 100 + 5;
int head[MAXN], cnt;
int m, n;
int d[MAXN], vis[MAXN];
queue<int>que;
struct Edge
{
int u, v, flow, ne;
int cap;
Edge(){}
Edge(int _u, int _v){u = _u, v = _v, ne = head[_u];}
}edge[MAXN * MAXN * 2];
void add_edge(int u, int v)
{
edge[cnt] = Edge(u, v);
edge[cnt].flow = 1, edge[cnt].cap = 1;
head[u] = cnt++;
edge[cnt] = Edge(v, u);
edge[cnt].flow = 0, edge[cnt].cap = 0;
head[v] = cnt++;
}
void init()
{
scanf("%d%d", &m, &n);
cnt = 0;
memset(head, -1, sizeof(head));
for(int i = 1 ; i <= m ; i++)
add_edge(0, i);
for(int i = m + 1 ; i <= n ; i++)
add_edge(i, n + 1);
int u, v;
while(1){
scanf("%d%d", &u, &v);
if(u == -1)
break;
add_edge(u, v);
}
}
bool BFS()
{
memset(vis, 0, sizeof(vis));
while(!que.empty()) que.pop();
vis[0] = 1;
d[0] = 0;
que.push(0);
while(!que.empty()){
int u = que.front(); que.pop();
for(int now = head[u] ; now != -1 ; now = edge[now].ne){
int v = edge[now].v;
if(!vis[v] && edge[now].flow > 0){
vis[v] = 1;
d[v] = d[u] + 1;
que.push(v);
}
}
}
return vis[n + 1];
}
int DFS(int u, int a)
{
if(u == n + 1 || a == 0)
return a;
int flow = 0, f;
for(int now = head[u] ; now != -1 ; now = edge[now].ne){
int v = edge[now].v;
if(d[v] == d[u] + 1 && (f = DFS(v, min(edge[now].flow, a)))){
edge[now].flow -= f;
edge[now ^ 1].flow += f;
flow += f;
a -= f;
if(a == 0) break;
}
}
return flow;
}
int Dinic()
{
int ans = 0;
while(BFS()){
ans += DFS(0, inf);
}
return ans;
}
int main()
{
// freopen("air0.in", "r", stdin);
init();
int ans = Dinic();
if(ans){
printf("%d\n", ans);
for(int i = 0 ; i < cnt ; i++){
int u = edge[i].u, v = edge[i].v;
if(edge[i].flow != edge[i].cap && u!=0 && u!=n+1 && v!=0 && v!=n+1 && u <= m && v >= m + 1)
printf("%d %d\n", u, v);
}
}
else
printf("No Solution!\n");
return 0;
}
ISAP:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
#define inf (1000000000)
const int MAXN = 100 + 5;
int m, n;
int head[MAXN], cnt;
int source, sink;
queue<int>que;
int p[MAXN];
int d[MAXN], cur[MAXN];
int vis[MAXN], num[MAXN];
struct Edge
{
int u, v, flow, ne;
int cap;
Edge(){}
Edge(int _u, int _v){u = _u, v = _v, ne = head[_u];}
}edge[MAXN * MAXN * 2];
void add_edge(int u, int v)
{
edge[cnt] = Edge(u, v);
edge[cnt].flow = 1, edge[cnt].cap = 1;
head[u] = cnt++;
edge[cnt] = Edge(v, u);
edge[cnt].flow = 0, edge[cnt].cap = 0;
head[v] = cnt++;
}
void init()
{
cnt = 0;
memset(head, -1, sizeof(head));
scanf("%d%d", &m, &n);
for(int i = 1 ; i <= m ; i++)
add_edge(0, i);
for(int i = m + 1 ; i <= n ; i++)
add_edge(i, n + 1);
int u, v;
while(scanf("%d%d", &u, &v) && u != -1)
add_edge(u, v);
source = 0, sink = n + 1;
}
void BFS(int t)
{
while(!que.empty()) que.pop();
memset(vis, 0, sizeof(vis));
memset(d, 0, sizeof(d));
d[t] = 0;
vis[t] = 1;
que.push(t);
while(!que.empty()){
int u = que.front(); que.pop();
for(int now = head[u] ; now != -1 ; now = edge[now].ne){
int v = edge[now].v;
if(vis[v] == 0){
vis[v] = 1;
d[v] = d[u] + 1;
que.push(v);
}
}
}
}
int Augment()
{
int ans = inf;
int now = sink;
while(now != source){
ans = min(ans, edge[p[now]].flow);
now = edge[p[now]].u;
}
return ans;
}
int ISAP(int s, int t)
{
BFS(t);
int flow = 0;
memset(num, 0, sizeof(num));
for(int i = 0 ; i <= n + 1 ; i++)
cur[i] = head[i];
for(int i = 0 ; i <= n + 1 ; i++)
num[d[i]]++;
int u = s;
while(d[s] < n + 1){
if(u == t){
flow += Augment();
u = s;
}
int ok = 0;
for(int &now = cur[u] ; now != -1 ; now = edge[now].ne){
int v = edge[now].v;
if(edge[now].flow > 0 && d[v] == d[u] - 1){
ok = 1;
p[v] = now;
u = v;
break;
}
}
if(!ok){
int tm = n + 1;
for(int now = head[u] ; now != -1 ; now = edge[now].ne){
if(edge[now].flow > 0)
tm = min(tm, d[edge[now].v]);
}
if(--num[d[u]] == 0) break;
num[tm + 1]++;
d[u] = tm + 1;
if(u != s) u = edge[p[u]].v;
}
}
return flow;
}
int main()
{
init();
int ans = ISAP(source, sink);
if(ans){
printf("%d\n", ans);
for(int i = 0 ; i < cnt ; i++){
int u = edge[i].u, v = edge[i].v;
if(edge[i].flow != edge[i].cap && u >= 1 && u <= m && v >= m + 1 && v <= n)
printf("%d %d\n", u, v);
}
}
return 0;
}