匈牙利算法.二分匹配(大部分题目都能用)

                                                    机器调度

Problem Description

有两台机器A和B以及N个需要运行的任务。

机器A有N种不同的模式,机器B有M种不同的模式,而每个任务都恰好在一台机器上运行。如果它在机器A上运行,则机器A需要设置为模式ai,如果它在机器B上运行,则机器B需要设置为模式bj。

特别说明:
开始的时候,两台机器分别处于a0和b0模式。
每台机器上的任务可以按照任意顺序执行,但是每台机器每转换一次模式都需要重启一次。
   
请合理为每个任务安排一台机器并合理安排顺序,使得机器重启次数尽量少。

Input

输入包含多组测试用例。

每组输的第一行是三个正整数N,M(N,M < 100)和k(k < 1000)。
接下来k行表示k个任务,每个任务包括三个元素i,x,y,表示编号是i的任务(i从0开始编号),可以在机器A的第x个模式运行,也可以在机器B的第y个模式上运行。

N为0时,输入结束~

Output

请输出完成所有的任务,机器需要重启的最少次数。
每组数据输出一行。

Sample Input

5 5 10
0 1 1
1 1 2
2 1 3
3 1 4
4 2 1
5 2 2
6 2 3
7 2 4
8 3 3
9 4 3
0

Sample Output

3


 

 
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1005;
int leftn,rightn;
int g[MAXN][MAXN];
int linker[MAXN];
bool vis[MAXN];
bool dfs(int a)//判断合法性和回溯(就这么理解吧) 
{
    for(int i=0;i<leftn;i++)
    {
        if(g[a][i]==1&&!vis[i])
        {
            vis[i]=true;
            if(linker[i]==-1||dfs(linker[i]))
            {
                linker[i]=a;
                return true;
            }
        }
    }
    return false;
} 
int hun()//匈牙利 算法 
{
    int sum=0;
    memset(linker,-1,sizeof(linker));
    for(int i=0;i<rightn;i++)
    {
        memset(vis,false,sizeof(vis));
        if(dfs(i)) 
            sum++;
    }
    return sum;
}
int main()
{    
    while(cin>>rightn&&rightn!=0)
    {
        int k;
        cin>>leftn>>k;
        memset(g,0,sizeof(g));
        int id,left,right;
        while(k--)
        {
            cin>>id>>left>>right;
            if(left!=0&&right!=0)//这个是题目专门的特判 
                g[left][right]=1;//如果ok,则可以匹配(连线) 
        }
        cout<<hun()<<endl;
    }
    return 0;
}


 

这个是最大匹配数,还有别的一些二分的东西都可以用匈牙利这么做

猜你喜欢

转载自blog.csdn.net/balalalalalalala/article/details/81143843