zoukankan      html  css  js  c++  java
  • 洛谷P3386 :【模板】二分图匹配

    https://www.luogu.org/problemnew/show/P3386

    题目描述

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

    输入输出格式

    输入格式:

    第一行,n,m,e

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

    输出格式:

    共一行,二分图最大匹配

    输入输出样例

    输入样例#1: 复制

    1 1 1
    1 1

    输出样例#1: 复制

    1

    说明

    n,m≤1000 , 1≤u≤n , 1≤v≤m,e≤n×m

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

    算法:二分图匹配

    未用邻接表:

    #include <stdio.h>
    #include <string.h>
    using namespace std;
    #define N 1020
    int e[N][N];
    int book[N], l[N], n, m;
    int dfs(int s)
    {
    	int i, len, j;
    	
    	for(i=1; i<=m; i++)
    	{
    		if(book[i]==0 && e[s][i])
    		{
    			book[i]=1;
    			if(l[i]==0 || dfs(l[i]))
    			{
    				l[i]=s;
    				return 1;
    			}
    		}
    	}
    	return 0;
    }
    int main()
    {
    	int i, j, u, v, ans, w;
    	scanf("%d%d%d", &n, &m, &w);
    	for(i=0; i<w; i++)
    	{
    		scanf("%d%d", &u, &v);
    		if(u>n || v>m)
    			continue;
    		e[u][v]=1;
    	}
    	ans=0;
    	for(i=1; i<=n; i++)
    	{
    		memset(book, 0, sizeof(book));
    		if(dfs(i))
    			ans++;
    	}
    	printf("%d
    ", ans);
    	return 0;
    } 

     邻接表写法:

    #include <stdio.h>
    #include <string.h>
    #include <vector>
    using namespace std;
    #define N 1020
    vector<int>e[N];
    int book[N], l[N];
    int dfs(int s)
    {
    	int i, len, j, x;
    	len=e[s].size();
    	for(i=0; i<len; i++)
    	{
    		x=e[s][i];
    		if(book[x]==0)
    		{
    			book[x]=1;
    			if(l[x]==0 || dfs(l[x]))
    			{
    				l[x]=s;
    				return 1;
    			}
    		}
    	}
    	return 0;
    }
    int main()
    {
    	int n, m, i, j, u, v, ans, w;
    	scanf("%d%d%d", &n, &m, &w);
    	memset(l, 0, sizeof(l));
    	for(i=0; i<w; i++)
    	{
    		scanf("%d%d", &u, &v);
    		if(u>n || v>m)
    			continue;
    		e[u].push_back(v);
    	}
    	ans=0;
    	for(i=1; i<=n; i++)
    	{
    		memset(book, 0, sizeof(book));
    		if(dfs(i))
    			ans++;
    	}
    	printf("%d
    ", ans);
    	return 0;
    } 

    网络最大流:

    #include <stdio.h>
    #include <string.h>
    #include <vector>
    #include <algorithm>
    using namespace std;
    #define N 2020
    int book[N], l[N], n, m, inf=99999999;
    struct edge{
    	int to;
    	int cap;
    	int rev;
    }; 
    vector<edge>G[N];
    void add (int from, int to)
    {
    	int cap=1;
    	G[from].push_back((edge){to, cap, G[to].size()});
    	G[to].push_back((edge){from, 0, G[from].size()-1});
    }
    int dfs(int v, int t, int f)
    {
    	int i;
    	if(v==t)
    		return f;
    	book[v]=1;
    	for(i=0; i<G[v].size(); i++)
    	{
    		edge &e=G[v][i];
    		if(!book[e.to] && e.cap>0){
    			int d=dfs(e.to, t, min(f, e.cap));
    			if(d>0)
    			{
    				//G[v][i].cap-=d;
    				e.cap-=d;
    				G[e.to][e.rev].cap+=d;
    				return d;
    			}
    		}
    	}
    	return 0;
    }
    int max_flow(int s, int t)
    {
    	int flow=0;
    	while(1)
    	//for(;;)
    	{
    		memset(book, 0, sizeof(book));
    		int f=dfs(s, t, inf);
    		if(f==0)
    			return flow;
    		flow+=f;
    	}
    }
    int main()
    {
    	int i, u, v, s;
    	scanf("%d%d%d", &n, &m, &s);
    	for(i=1; i<=n; i++)
    		add(0,i);
    	for(i=n+1; i<=n+m; i++)
    		add(i, m+n+1);
    	while(s--)
    	{
    		scanf("%d%d", &u, &v);
    		if(v>m || u>n)
    			continue;
    		add(u, v+n);
    	}
    	printf("%d
    ", max_flow(0, n+m+1));
    	return 0;
    }
  • 相关阅读:
    笨笨的洪水堵截
    青蛙的约会
    扩展欧几里德
    windows上修改路由表
    怎样编写注册表文件
    win7启动文件修复
    word文档中的字号和磅的对应关系
    将Windows 7导航窗格中的收藏夹、库、家庭组、网络全部去掉
    DNS
    UTF-8 GBK GB2312 之间的区别和关系
  • 原文地址:https://www.cnblogs.com/zyq1758043090/p/11852637.html
Copyright © 2011-2022 走看看