zoukankan      html  css  js  c++  java
  • 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 */
  • 相关阅读:
    图片轮播
    带箭头的轮播
    日期时间函数(需要用变量调用):
    DOM:文档对象模型 --树模型
    js脚本语言(数组)
    查询例子
    10.17 (下午)开课一个月零十三天 (高级查询)
    10.17 (上午)开课一个月零十三天 (数据库查询)
    10.16 (下午)开课一个月零十二天 (增删改查)
    10.16 (上午)开课一个月零十二天 (创建数据库,创建表)
  • 原文地址:https://www.cnblogs.com/lyqlyq/p/7794467.html
Copyright © 2011-2022 走看看