uva 10092 The Problem with the Problem Setter 二分图匹配 匈牙利算法

来源:互联网 发布:孙振耀。知乎 编辑:程序博客网 时间:2024/06/05 13:07

题意:第一行k,p  分别为 题目的类别数 题目的个数

第二行k个数   为每类题的个数

接下来p行 每行第一个数(设为n)为 该题可被划分到的类别的个数  接下来n个数为 可被划分到第几个类别

然后题目希望你能把这些题划分到他可以被划分到的类 使得最后每类题的数量达到要求。

首先想到这是二分图匹配 然后想了一下 从以前做过的题目中找到了灵感

就是把要求的数量拆开 比如第一个样例 三类题 1 2 3 要求数量为 3 3 4

那么我就可以拆分成十个点 前三个标志为1 接下来三个标志为 2 后四个点标志为3 ,添加标志是为了方便接下来建边

拆分,标记完之后就可以建边了 如果这个点可以被分配的类别与标志相同 就建一条边

然后就可以进行匈牙利算法了,返回值和n比 ,相同则输出1 然后把匈牙利算法中的存匹配的点的数组对应输出即可

不同则输出0


#include<bits/stdc++.h>using namespace std;const int maxn=100005;struct Edge{    int from;    int to;    Edge(int f, int t):from(f), to(t){}};vector<int> G[maxn];vector<Edge> edges;int matching[maxn];int check[maxn];queue<int> Q;int n;int prev1[maxn];int Hungarian(){    int ans = 0;    memset(matching, -1, sizeof(matching));    memset(check, -1, sizeof(check));    for (int i=0;i<n; ++i)    {        if (matching[i] == -1)        {            while (!Q.empty()) Q.pop();            Q.push(i);            prev1[i]=-1;            bool flag = false;            while (!Q.empty() && !flag)            {                int u = Q.front();                for (auto ix = G[u].begin(); ix != G[u].end() && !flag; ++ix)                {                    int v = edges[*ix].to;                    if (check[v] != i) {                        check[v] = i;                        Q.push(matching[v]);                        if (matching[v] >= 0)                        {                            prev1[matching[v]] = u;                        }                        else                        {                            flag = true;                            int d=u, e=v;                            while (d != -1)                            {                                int t = matching[d];                                matching[d] = e;                                matching[e] = d;                                d = prev1[d];                                e = t;                            }                        }                    }                }                Q.pop();            }            if (matching[i] != -1) ++ans;        }    }    return ans;}int num[105];int match[105];int main(){    int i,j,k,s,v,p,m,x,y;    while(cin>>k>>p)    {        if(k==0&&p==0)            break;        n=0;        for(i=1;i<=k;i++)        {            cin>>num[i];            for(j=0;j<num[i];j++)                match[n++]=i;        }        for(i=0;i<p;i++)        {            cin>>m;            for(j=0;j<m;j++)            {                cin>>x;                for(y=0;y<n;y++)                {                    if(match[y]==x)                    {                        edges.push_back(Edge(y,i+n));                        G[y].push_back(edges.size()-1);                    }                }            }        }        int ans=Hungarian();        if(ans==n)        {            cout<<'1'<<endl;            int res=0;            for(i=1;i<=k;i++)            {                for(j=0;j<num[i];j++)                {                    cout<<matching[res++]-n+1<<' ';                }                cout<<endl;            }        }        else cout<<'0'<<endl;        for(i=0;i<n+m;i++)            G[i].clear();        edges.clear();    }    return 0;}








阅读全文
0 0