二分图匹配
很多人都用的是匈牙利算法,但其实网络瘤也可过。
出一个数据:
Input:
4 4 6
1 1
1 3
2 1
2 2
3 1
4 1
Output:
3
图是这个样子的:
那我们网络瘤不就只用加个源点和汇点么:
只用把限度都设为\(1\)就好了。
const int M = 3000010, N = 10010;
int n, m, s, t, tot, ee;
struct edge
{
int y, w, op, next;
} e[M];
int head[N];
void Add(int x, int y, int w)
{
e[++tot] = (edge){y, w, tot + 1, head[x]};
head[x] = tot;
e[++tot] = (edge){x, 0, tot - 1, head[y]};
head[y] = tot;
}
//****************************************
//**************网络流*********************
//****************************************
int dis[N];
queue <int> que;
bool bfs()
{
while(!que.empty())que.pop();
memset(dis, 60, sizeof(dis));
dis[s] = 0;
que.push(s);
while(!que.empty())
{
int x = que.front();que.pop();
for (int i = head[x]; i; i = e[i].next)
{
int y = e[i].y;
if(dis[y] >= dis[x] + 1 && e[i].w)
{
dis[y] = dis[x] + 1;
if(y == t) return 1;
que.push(y);
}
}
}
return 0;
}
ll dfs(int x, ll f)
{
if(x == t) return f;
ll sum = 0;
for (int i = head[x]; i; i = e[i].next)
{
int y = e[i].y;
if(dis[y] == dis[x] + 1 && e[i].w)
{
ll f2 = dfs(y, min(e[i].w * 1ll, f - sum));
if (!f2) dis[y] = -1;
e[i].w -= f2;
e[e[i].op].w += f2;
sum += f2;
if (sum == f) break;
}
}
return sum;
}
ll dinic()
{
ll sum = 0;
while(bfs()){sum += dfs(s, 1010580540);}
return sum;
}
//****************************************
//***************main*********************
//****************************************
int main()
{
scanf("%d%d%d", &n, &m, &ee);
s = n + m + 1, t = n + m + 2;
for (int i = 1; i <= ee; i++)
{
int x, y, w = 1;
scanf("%d%d", &x, &y);
y += n;
Add(x, y, w);
}
for (int i = 1; i <= n; i++) Add(s, i, 1); //连源点
for (int i = 1; i <= m; i++) Add(i + n, t, 1);//连汇点
printf("%lld", dinic());
return 0;
}
原文:https://www.cnblogs.com/GJY-JURUO/p/12109923.html