P3386 【模板】二分图匹配

题目背景

二分图

题目描述

给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数

输入输出格式

输入格式:

 

第一行,n,m,e

第二至e+1行,每行两个正整数u,v,表示u,v有一条连边

 

输出格式:

 

共一行,二分图最大匹配

 

输入输出样例

输入样例#1: 复制
1 1 1
1 1
输出样例#1: 复制
1

说明

n,m \leq 1000n,m1000, 1 \leq u \leq n1un, 1 \leq v \leq m1vm

因为数据有坑,可能会遇到 v>mv>m 的情况。请把 v>mv>m 的数据自觉过滤掉。

算法:二分图匹配

 

不知为啥,跑的真慢

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>

using namespace std;
const int N = 2010;

#define oo 99999999

int n, m, S, T, now;
int dis[N], head[N];
bool vis[N];
struct Node{
    int u, v, nxt, cap;
}E[N * N];
queue <int> Q;

inline int read(){
    int x = 0; char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x;
}

inline void add(int u, int v, int w){
    E[now].u = u;
    E[now].v = v;
    E[now].cap = w;
    E[now].nxt = head[u];
    head[u] = now ++;
}

inline bool bfs(int start){
    for(int i = S; i <= T; i ++) dis[i] = -1;
    dis[start] = 0;
    Q.push(start);
    while(!Q.empty()){
        int topp = Q.front();
        Q.pop();
        vis[topp] = 0;
        for(int i = head[topp]; ~ i; i = E[i].nxt){
            int v = E[i].v; //cout << v <<" ";
            if(dis[v] == -1 && E[i].cap > 0){
                dis[v] = dis[topp] + 1;
                if(!vis[v]){
                    vis[v] = 1;
                    Q.push(v);
                }
            }
        }
    }
    return dis[T] != -1;
}

int dfs(int now, int minn){
    if(now == T || minn <= 0) return minn;
    int retflow = 0;
    for(int i = head[now]; ~ i; i = E[i].nxt){
        int v = E[i].v;
        if(dis[v] == dis[now] + 1 && E[i].cap){
            int f = dfs(v, min(minn, E[i].cap));
            retflow += f;
            E[i].cap -= f;
            E[i ^ 1].cap += f;
            minn -= f;
            if(minn <= 0) break;
        }
    }
    return retflow;
}
inline
void Dinic(){ int answer = 0; while(bfs(S)) answer += dfs(S, oo); printf("%d", answer); } int main() { //freopen("gg.in", "r", stdin); n = read(); m = read(); int z = read(); int a, b; S = 0, T = n + m + 1; for(int i = S; i <= T; i ++) head[i] = -1; for(int i = 1; i <= z; i ++){ int u = read(); int v = read(); if(v > m) continue ; add(u, v + n, 1); add(v + n, u, 0); } for(int i = 1; i <= n; i ++) add(S, i, 1), add(i, S, 0); for(int i = n + 1; i <= n + m; i ++) add(i, T, 1), add(T, i, 0); Dinic(); return 0; } /* 1 1 1 1 1 */

 

posted @ 2017-11-06 18:08  ioioioioioio  阅读(219)  评论(0编辑  收藏  举报