码迷,mamicode.com
首页 > 其他好文 > 详细

二分图算法模板汇总

时间:2014-09-25 12:12:28      阅读:145      评论:0      收藏:0      [点我收藏+]

标签:acm   二分图   算法   

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=n;
    next=NULL;
}
int n1,n2,m,ans=0;
int result[101]; //记录n1中的点匹配的点的编号
bool state [101]; //记录n1中的每个点是否被搜索过
link *head [101]; //记录n2中的点的邻接节点
link *last [101]; //邻接表的终止位置记录
//判断能否找到从节点n开始的增广路
bool find(const int n) {
    link* t=head[n];
    while (t!=NULL) { //n仍有未查找的邻接节点时
        if (!(state[t->data])) { //如果邻接点t->data未被查找过
            state[t->data]=true; //标记t->data为已经被找过
            if ((result[t->data]==0) || //如果t->data不属于前一个匹配M
            (find(result[t->data]))) { //如果t->data匹配到的节点可以寻找到增广路
                result[t->data]=n; //那么可以更新匹配M',其中n1中的点t->data匹配n
                return true; //返回匹配成功的标志
            }
        }
        t=t->next; //继续查找下一个n的邻接节点
    }
    return false;
}
int main() {
    int t1=0,t2=0;
    cin>>n1>>n2>>m;
    for (int i=0; i<m; i++) {
        cin>>t1>>t2;
        if (last[t1]==NULL)
            last[t1]=head[t1]=new link(t2);
        else
            last[t1]=last[t1]->next=new link(t2);
    }
    for (int i=1; i<=n1; i++) {
        memset(state,0,sizeof(state));
        if (find(i)) ans++;
    }
    cout<<ans<<endl;
    return 0;
}

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=n;
    next=NULL;
}
int n1,n2,m,ans=0;
int result[101]; //记录n1中的点匹配的点的编号
bool state [101]; //记录n1中的每个点是否被搜索过
link *head [101]; //记录n2中的点的邻接节点
link *last [101]; //邻接表的终止位置记录
//判断能否找到从节点n开始的增广路
bool find(const int n) {
    link* t=head[n];
    while (t!=NULL) { //n仍有未查找的邻接节点时
        if (!(state[t->data])) { //如果邻接点t->data未被查找过
            state[t->data]=true; //标记t->data为已经被找过
            if ((result[t->data]==0) || //如果t->data不属于前一个匹配M
            (find(result[t->data]))) { //如果t->data匹配到的节点可以寻找到增广路
                result[t->data]=n; //那么可以更新匹配M',其中n1中的点t->data匹配n
                return true; //返回匹配成功的标志
            }
        }
        t=t->next; //继续查找下一个n的邻接节点
    }
    return false;
}
int main() {
    int t1=0,t2=0;
    cin>>n1>>n2>>m;
    for (int i=0; i<m; i++) {
        cin>>t1>>t2;
        if (last[t1]==NULL)
            last[t1]=head[t1]=new link(t2);
        else
            last[t1]=last[t1]->next=new link(t2);
    }
    for (int i=1; i<=n1; i++) {
        memset(state,0,sizeof(state));
        if (find(i)) ans++;
    }
    cout<<ans<<endl;
    return 0;
}


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;
}



二分图算法模板汇总

标签:acm   二分图   算法   

原文地址:http://blog.csdn.net/u014767460/article/details/39545793

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!