网络流
dinic算法
dining
模型详见dining
AC代码:
#include <limits.h>
#include <iostream>
#include <stdlib.h>
#include <assert.h>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cstring>
#define Maxn 500
#define Maxm (Maxn*Maxn+4*Maxn)
using namespace std;
typedef long long LL;
struct edge {
int v, cap, next;
};
edge e[Maxm];
int num_of_edges;
int head[Maxn], level[Maxn], cur[Maxn];
void dicnic_init(void) {
num_of_edges = 0;
memset(head, -1, sizeof(head));
return;
}
int add_edge(int u, int v, int c1, int c2) {
int& i = num_of_edges;
assert(c1>=0 && c2>=0 && c1+c2>=0);
e[i].v = v;
e[i].cap = c1;
e[i].next = head[u];
head[u] = i++;
e[i].v = u;
e[i].cap = c2;
e[i].next = head[v];
head[v] = i++;
return i;
}
int dfs(int u, int t, int bn) {
if(u == t) return bn;
int left = bn;
for(int &i=cur[u]; i>=0; i=e[i].next) {
int v = e[i].v;
int c = e[i].cap;
if(c>0 && level[u]+1==level[v]) {
int flow = dfs(v, t, min(left, c));
if(flow > 0) {
e[i].cap -= flow;
e[i^1].cap += flow;
cur[u] = i;
left -= flow;
if(!left) break;
}
}
}
if(left > 0) level[u] = 0;
return bn-left;
}
bool bfs(int s, int t) {
memset(level, 0, sizeof(level));
level[s] = 1;
queue<int> q;
q.push(s);
while(!q.empty()) {
int u = q.front();
q.pop();
if(u == t) return true;
for(int i=head[u]; i>=0; i=e[i].next) {
int v = e[i].v;
if(!level[v] && e[i].cap>0) {
level[v] = level[u] + 1;
q.push(v);
}
}
}
return false;
}
LL dinic(int s, int t) {
LL max_flow = 0;
while(bfs(s, t)) {
memcpy(cur, head, sizeof(head));
max_flow += dfs(s, t, INT_MAX);
}
return max_flow;
}
int main(int argc, const char * argv[]) {
int N, F, D, s = 0, t, total = 0;
scanf("%d%d%d", &N, &F, &D);
t = 2*N + F + D + 1;
dicnic_init();
for(int i=1; i<=N; i++) {
int Fnum, Dnum, temp;
scanf("%d%d", &Fnum, &Dnum);
for(int j=1; j<=Fnum; j++) {
scanf("%d", &temp);
add_edge(temp, i+F, 1, 0);
}
for(int j=1; j<=Dnum; j++) {
scanf("%d", &temp);
add_edge(i+F+N, temp+2*N+F, 1, 0);
}
}
for(int i=1; i<=N; i++) {
add_edge(i+F, i+N+F, 1, 0);
}
for(int i=1; i<=F; i++) {
add_edge(s, i, 1, 0);
}
for(int i=1; i<=D; i++) {
add_edge(i+F+2*N, t, 1, 0);
}
int flow = dinic(s, t);
cout<<flow<<endl;
return 0;
}
dual core CPU
最大匹配
最小路径覆盖
关于最小路径覆盖详情见最小路径覆盖
AC代码
#include <iostream>
#include <limits.h>
#include <cstring>
#include <assert.h>
#include <stdlib.h>
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
vector<vector<int> > lnklst;
vector<int> l, r;
vector<bool> visited;
void init(int n1, int n2) {
lnklst.clear(); lnklst.resize(n1+1);
l.clear(); l.resize(n1+1,-1);
r.clear(); r.resize(n2+1,-1);
return;
}
void add_edge(int u, int v) {
lnklst[u].push_back(v);
return;
}
bool dfs(int u) {
for (int i=0; i<lnklst[u].size(); i++) {
int v = lnklst[u][i];
if (visited[v]) continue;
visited[v] = true;
if (r[v] < 0 || dfs(r[v])) {
l[u] = v;
r[v] = u;
return true;
}
}
return false;
}
int greedy_match(int n1) {
int match = 0;
for (int u=0; u<n1; u++) {
if (l[u] < 0) {
for (int i=0; i<lnklst[u].size(); i++) {
int v = lnklst[u][i];
if (r[v] < 0) {
l[u] = v;
r[v] = u;
match++;
break;
}
}
}
}
return match;
}
int hungarian(void) {
int n1 = l.size();
int n2 = r.size();
int match = greedy_match(n1);
for (int u=0; u<n1; u++) {
if (l[u] < 0) {
visited.clear();
visited.resize(n2);
if (dfs(u)) {
match++;
}
}
}
return match;
}
int main(int argc, const char * argv[]) {
int n, m;
cin>>m>>n;
init(n, n);
for(int i=0; i<m; i++) {
int temp1, temp2;
scanf("%d%d", &temp1, &temp2);
add_edge(temp1, temp2);
}
int max_match = hungarian();
cout<<n-max_match<<endl;
return 0;
}