二分圖算法模板彙總

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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章