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;
    }
  • 相关阅读:
    poj 3068 Bridge Across Islands
    XidianOJ 1086 Flappy v8
    XidianOJ 1036 分配宝藏
    XidianOJ 1090 爬树的V8
    XidianOJ 1088 AK后的V8
    XidianOJ 1062 Black King Bar
    XidianOJ 1091 看Dota视频的V8
    XidianOJ 1098 突击数论前的xry111
    XidianOJ 1019 自然数的秘密
    XidianOJ 1109 Too Naive
  • 原文地址:https://www.cnblogs.com/zyq1758043090/p/11852637.html
Copyright © 2011-2022 走看看