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 的数据自觉过滤掉。

    算法:二分图匹配

    题解

    • 看这题目也看着像板题,就是模板题,匈牙利、最大流两种做法

    代码1

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <queue>
     4 #define inf 0x3f3f3f3f
     5 using namespace std;
     6 queue<int>Q;
     7 struct edge {int to,from,v;}e[2001000];
     8 int n,m,num,cnt,ans,s,t,dis[1010*4],head[1010*4],cur[1010*4];
     9 void insert(int x,int y,int z) { e[++cnt].to=y,e[cnt].from=head[x],e[cnt].v=z,head[x]=cnt; }
    10 bool bfs()
    11 {
    12     for (int i=s;i<=t;i++) dis[i]=0; dis[s]=1;
    13     while (!Q.empty()) Q.pop(); Q.push(s);
    14     while (!Q.empty())
    15     {
    16         int u=Q.front(); Q.pop();
    17         for (int i=head[u];i;i=e[i].from)
    18             if (e[i].v&&!dis[e[i].to])
    19             {
    20                 dis[e[i].to]=dis[u]+1;
    21                 if (e[i].to==t) return 1;
    22                 Q.push(e[i].to);
    23             }
    24     }
    25     return 0;
    26 }
    27 int dfs(int x,int mx)
    28 {
    29     if (x==t||!mx) return mx;
    30     int r=0;
    31     for (int &i=cur[x];i;i=e[i].from)
    32         if (e[i].v&&dis[e[i].to]==dis[x]+1)
    33         {
    34             int k=dfs(e[i].to,min(e[i].v,mx-r));
    35             e[i].v-=k; 
    36             if (i&1) e[i+1].v+=k; else e[i-1].v+=k;
    37             r+=k;
    38             if (r==mx) break;
    39         }
    40     return r;
    41 }
    42 void dinic()
    43 {
    44     while (bfs())
    45     {
    46         for (int i=s;i<=t;i++) cur[i]=head[i];
    47         ans+=dfs(s,inf);
    48     }
    49 }
    50 int main()
    51 {
    52     scanf("%d%d%d",&n,&m,&num);
    53     for (int i=1,x,y;i<=num;i++)
    54     {
    55         scanf("%d%d",&x,&y);
    56         if (x<=n&&y<=m)    insert(x,y+n,1),insert(y+n,x,0);
    57     }
    58     for (int i=1;i<=n;i++) insert(0,i,1),insert(i,0,0);
    59     for (int i=1;i<=m;i++) insert(n+i,n+m+1,1),insert(n+m+1,n+i,0);
    60     s=0,t=n+m+1,dinic();
    61     printf("%d",ans);
    62 }

    代码2

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 using namespace std;
     5 int n,m,num,ans,cnt,head[1010],p[1010];
     6 bool a[1010][1010],visit[1010];
     7 int xyl(int x)
     8 {
     9     for (int i=1;i<=n;i++)
    10         if (a[x][i]==true&&visit[i]==0)
    11         {
    12             visit[i]=1;
    13             if (p[i]==0||xyl(p[i]))
    14             {
    15                 p[i]=x;
    16                 return 1;
    17             }
    18         }
    19     return 0;
    20 }
    21 int main()
    22 {
    23     scanf("%d%d%d",&n,&m,&num);
    24     for (int i=1,x,y;i<=num;i++) 
    25     {
    26         scanf("%d%d",&x,&y);
    27         if (x<=n&&y<=m) a[x][y]=1;
    28     }
    29     for (int i=1;i<=n;i++) memset(visit,0,sizeof(visit)),ans+=xyl(i);
    30     printf("%d",ans);
    31 }
  • 相关阅读:
    微信公众平台--5.其他
    微信公众平台--4.接收事件推送消息
    微信公众平台--3.普通消息交互(发送与接收)
    微信公众平台--2.获取接口调用凭据
    微信公众平台--1.开发者接入
    PHP的几种缓存方式
    缓存时PHP读写文件的方法
    PHP接收post过来的xml数据
    PHP CURL上传文件
    Linux常用命令ps,kill
  • 原文地址:https://www.cnblogs.com/Comfortable/p/9805101.html
Copyright © 2011-2022 走看看