首页 > 代码库 > 二分图算法模板汇总

二分图算法模板汇总

Hungary算法

.c

#include <std<pre name="code" class="cpp">#include <iostream>
#include <cstring>
using namespace std;
//定义链表
struct link {
    int data; //存放数据
    link* next; //指向下一个节点
    link(int=0);
};
link::link(int n) {
    data=http://www.mamicode.com/n;>
io.h>#include <string.h>int n1,n2,m,ans;int result[101]; //记录V2中的点匹配的点的编号bool state [101]; //记录V2中的每个点是否被搜索过bool data[101][101];//邻接矩阵 true代表有边相连void init() { int t1,t2; memset(data,0,sizeof(data)); memset(result,0,sizeof(result)); ans = 0; scanf("%d%d%d",&n1,&n2,&m); for (int i = 1; i <= m; i++) { scanf("%d%d",&t1,&t2); data[t1][t2] = true; } return;}bool find(int a) { for (int i = 1; i <= n2; i++) { if (data[a][i] == 1 && !state[i]) { //如果节点i与a相邻并且未被查找过 state[i] = true; //标记i为已查找过 if (result[i] == 0 //如果i未在前一个匹配M中 || find(result[i])) { //i在匹配M中,但是从与i相邻的节点出发可以有增广路 result[i] = a; //记录查找成功记录 return true; //返回查找成功 } } } return false;}int main() { init(); for (int i = 1; i <= n1; i++) { memset(state,0,sizeof(state)); //清空上次搜索时的标记 if (find(i)) ans++; //从节点i尝试扩展 } printf("%d\n",ans); return 0;}



.cpp

#include<iostream>
#include<cstring>
using namespace std;
int map[105][105];
int visit[105],flag[105];
int n,m;
bool dfs(int a) {
    for(int i=1;i<=n;i++) {
        if(map[a][i] && !visit[i]) {
            visit[i]=1;
            if(flag[i]==0 || dfs(flag[i])) {
                flag[i]=a;
                return true;
            }
        }
    }
    return false;
}
int main() {
    while(cin>>n>>m) {
        memset(map,0,sizeof(map));
        for(int i=1;i<=m;i++) {
            int x,y;
            cin>>x>>y;
            map[x][y]=1;
        }
        memset(flag,0,sizeof(flag));
        int result=0;
        for(int i=1;i<=n;i++) {
            memset(visit,0,sizeof(visit));
            if(dfs(i)) result++;
        }
        cout<<result<<endl;
    }
    return 0;
}


link.cpp

#include <iostream>
#include <cstring>
using namespace std;
//定义链表
struct link {
    int data; //存放数据
    link* next; //指向下一个节点
    link(int=0);
};
link::link(int n) {
    data=http://www.mamicode.com/n;>

byvoid

#include <stdio.h>
#include <string.h>
#define MAX 102

long n,n1,match;
long adjl[MAX][MAX];
long mat[MAX];
bool used[MAX];

FILE *fi,*fo;

void readfile()
{
    fi=fopen("flyer.in","r");
    fo=fopen("flyer.out","w");
    fscanf(fi,"%ld%ld",&n,&n1);
    long a,b;
    while (fscanf(fi,"%ld%ld",&a,&b)!=EOF)
        adjl[a][ ++adjl[a][0] ]=b;
    match=0;
}

bool crosspath(long k)
{
    for (long i=1;i<=adjl[k][0];i++)
    {
        long j=adjl[k][i];
        if (!used[j])
        {
            used[j]=true;
            if (mat[j]==0 || crosspath(mat[j]))
            {
                mat[j]=k;
                return true;
            }
        }
    }
    return false;
}

void hungary()
{
    for (long i=1;i<=n1;i++)
    {
        if (crosspath(i))
            match++;
        memset(used,0,sizeof(used));
    }
}

void print()
{
    fprintf(fo,"%ld",match);
    fclose(fi);
    fclose(fo);
}

int main()
{
    readfile();
    hungary();
    print();
    return 0;
}

Horcroft-Karp

#include<stdio.h>
#include<queue>
#include<iostream>
#include<string.h>
#include<math.h>
using namespace std;
#define eps 1e-6

const int MAXN=3005;
const int INF=1<<28;
int g[MAXN][MAXN];
int Mx[MAXN],My[MAXN];// Mx[i]表示xi对应的匹配,My[i]表示yi对应的匹配.
int Nx,Ny;
int dx[MAXN],dy[MAXN],dis;// 层的概念,即在BFS中的第几层.
bool vst[MAXN];
struct Node1
{
    int x,y,s;
}guests[MAXN];
struct Node2
{
    int x,y;
}um[MAXN];
double distance(Node1 a,Node2 b)
{
    double x=a.x-b.x;
    double y=a.y-b.y;

    return sqrt(x*x+y*y);
}
/*
首先从所有X的未盖点进行BFS,
BFS之后对每个X节点和Y节点维护距离标号,
如果Y节点是未盖点那么就找到了一条最短增广路,
BFS完之后就找到了最短增广路集,
随后可以直接用DFS对所有允许弧(dist[y]=dist[x]+1,
可以参见高流推进HLPP的实现)进行类似于匈牙利中寻找增广路的操作,
这样就可以做到O(m)的复杂度。
*/
bool searchP()
{
    queue<int>Q;
    dis=INF;
    memset(dx,-1,sizeof(dx));
    memset(dy,-1,sizeof(dy));
    for(int i=0;i<Nx;i++)
        if(Mx[i]==-1)//将未匹配x集合中元素入队列
        {
            Q.push(i);
            dx[i]=0;
        }
    while(!Q.empty())
    {
        int u=Q.front();
        Q.pop();
        if(dx[u]>dis)  break;
        for(int v=0;v<Ny;v++)
            if(g[u][v]&&dy[v]==-1)
            {
                dy[v]=dx[u]+1;
                if(My[v]==-1)  dis=dy[v];
                else
                {
                    dx[My[v]]=dy[v]+1;
                    Q.push(My[v]);
                }
            }
    }
    return dis!=INF;
}
bool DFS(int u)
{
    for(int v=0;v<Ny;v++)
       if(!vst[v]&&g[u][v]&&dy[v]==dx[u]+1)
       {
           vst[v]=1;
           if(My[v]!=-1&&dy[v]==dis) continue;
           if(My[v]==-1||DFS(My[v]))
           {
               My[v]=u;
               Mx[u]=v;
               return 1;
           }
       }
    return 0;
}
int HK()
{
    int res=0;
    memset(Mx,-1,sizeof(Mx));
    memset(My,-1,sizeof(My));
    while(searchP())
    {
        memset(vst,0,sizeof(vst));
        for(int i=0;i<Nx;i++)
          if(Mx[i]==-1&&DFS(i))  res++;
    }
    return res;
}

int main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.out","w",stdout);
    int n,m,t,i,j;
    int T,iCase=0;
    scanf("%d",&T);
    while(T--)
    {
        iCase++;
        scanf("%d",&t);
        scanf("%d",&m);
        for(i=0;i<m;i++)
           scanf("%d%d%d",&guests[i].x,&guests[i].y,&guests[i].s);
        scanf("%d",&n);
        for(i=0;i<n;i++)
           scanf("%d%d",&um[i].x,&um[i].y);
        Nx=m;Ny=n;
        memset(g,0,sizeof(g));
        for(i=0;i<m;i++)
        {
           for(j=0;j<n;j++)
           {
               if(distance(guests[i],um[j])/guests[i].s-t<eps)
               {
                   g[i][j]=1;
               }
           }
        }
        printf("Scenario #%d:\n%d\n\n",iCase,HK());
    }
    return 0;
}



二分图算法模板汇总