您的位置:首页 > 其它

图的最大匹配问题: poj_1469

2016-03-10 21:05 211 查看
#include <iostream>

//二分图的最大匹配问题,POJ149

//匈牙利算法

/*最大流算法的核心问题就是找增广路径(augment path)。匈牙利算法也不例外,它的基本模式就是:

     初始时最大匹配为空

      while 找得到增广路径

               do 把增广路径加入到最大匹配中去

    最小点覆盖数: 最小覆盖要求用最少的点(X集合或Y集合的都行)让每条边都至少和其中一个点关联。

    可以证明:最少的点(即覆盖数)=最大匹配数

    最小路径覆盖=最小路径覆盖=|N|-最大匹配数

    用尽量少的不相交简单路径覆盖有向无环图G的所有结点。解决此类问题可以建立一个二分图模型。

    把所有顶点i拆成两个:X结点集中的i和Y结点集中的i',

    如果有边i->j,则在二分图中引入边i->j',设二分图最大匹配为m,则结果就是n-m。

*/

using namespace std;

bool g[110][310];//邻接矩阵,100门课程,300个学生。

bool flag,visited[310];//记录某个学生是否被访问过

int match[310];//记录与学生匹配的课程号

int p,n;//课程数和学生人数

int link[110];

bool dfs(int u){

    for(int i =1;i<=n;i++){

        if(g[u][i]&&!visited[i]){//如果节点i与节点u可以相连并且未被访问过

            visited[i] = true;//标记其被查过

            if(match[i]==-1 || dfs(match[i])) //如果i未在之前的匹配中,或者i在

            //之前的匹配m中,但是从与i相邻的节点出发可以由增广路径

            {

                match[i] = u;//记录查找成功的记录,更新匹配

                return true;

            }

        }

    }

    return false;

}

int main()

{

    int i,j,k,t,v,ans;

    cin>>t;

    while(t--){

        cin>>p>>n;

        for(i=1;i<=p;i++){

            for(j=1;j<=n;j++)

            g[i][j] = false;

        }

        for(i=1;i<=n;i++)

            match[i] = -1;

        flag =true;

        for(i=1;i<=p;i++){

            cin>>k;

            if(k==0)

                flag =false;

            while(k--){

                cin>>v;

                g[i][v] = true;

            }

        }

        if(flag){

            ans =0;

            for(i=1;i<=p;i++){

                for(j=1;j<=300;j++)

                    visited[j] = false;

                if(dfs(i))

                    ans++;

            }

            if(ans==p){

                cout<<"YES!"<<endl;

                cout<<"最大匹配是:";

                for(i=1;i<=300;i++){

                    if(match[i] !=-1){

                        link[match[i]] = i;

                    }

                }

                for(j =1;j<=p;j++){

                    cout<<j<<"->"<<link[j]<<endl;

                }

            }

            else

                cout<<"NO"<<endl;

        }

        else

            cout<<"NO"<<endl;

    }

    //cout << "Hello world!" << endl;

    return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: