牛客竞赛 20648-国政议事 (二分图匹配)

题目链接:
https://ac.nowcoder.com/acm/problem/20648
题意:
有n个人,m个任务,每个任务有ai和bi两个参数,表示任务在ai手里,ai要交给bi处理。求最多能处理几个任务,在保证任务处理数量最大的情况下,有多少任务是必须要处理的。并且输出必须处理任务的编号。
题解:
二分图匹配,先利用匈牙利算法得到最大匹配数。然后依次删边,判断每条边删除后是否影响最大匹配数,如果影响,则为必须处理的任务,若不影响的话,则不是必须要处理的任务。
AC代码:

#include <bits/stdc++.h>
using namespace std;
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
const int maxn = 20010;
int u[maxn],v[maxn];
int mp[maxn][maxn] , used[maxn] , match[maxn];
int n , m ,Index;
int ans[maxn];
bool found(int x)
{
    for(int i = 1 ; i <= n ; i ++)
    {
        if(mp[x][i])
        {
            if(used[i] != Index)
            {
                used[i] = Index;
                if(!match[i] || found(match[i]))
                {
                    match[i] = x;
                    return 1;
                }
            }
        }
    }
    return 0;
}
int xiong()
{
    memset(match,0,sizeof(match));
    int ans = 0 ;
    for(int i = 1 ; i <= n ; i++)
    {
        Index ++;
        ans += found(i);
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    for(int  i = 0 ; i < m ; i++)
    {
        cin>>u[i]>>v[i];
        mp[u[i]][v[i]]++;
    }
    int ANS = xiong();
    int cnt = 0;
    for(int i = 0 ; i < m ; i ++)
    {
        mp[u[i]][v[i]] -- ;
        if(xiong() < ANS) ans[cnt++] = i;
        mp[u[i]][v[i]] ++ ;
    }
    cout<<ANS<<" "<<cnt<<"\n";
    for(int i = 0 ; i < cnt ; i ++)
        cout<<ans[i]+1<<"\n";
}

欢迎评论!

猜你喜欢

转载自blog.csdn.net/wjl_zyl_1314/article/details/102548191