avatar
fireworks99
keep hungry keep foolish

HDU 1083 2063 ZOJ 4120(二分图匹配)

确定是二分图求最大匹配时,对任意一方查找匹配均可

记录:link[i] = v; 选项i(下标) 分配给任务v(储存值)

数组vis

记录:在为任务v配对时 选项i(下标)是否被访问过

作用:为了替任务v争得选项to,在此处将选项to锁定,dfs寻找选项(to) 原来服务的任务(link[to]) 其他可行的选项,体现了增广路的特点——反悔

注意

每次为任务选择选项时,每个选项要从头考虑(memset(vis, 0, sizeo(vis))),直到找到合适的选项为止

HDU 1083

题意:P课程各找一个课代表,N个人,每人至多担任一门课代表

#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

int p, n;
int link[1005];///link[i] = v; 选项i 分配给任务v
bool vis[1005];///在为任务v配对时 选项i是否被访问过
vector<int> vec[1005];

/*
vis数组的作用:
///为了替任务v争得选项to,在此处将选项to锁定,
dfs寻找选项(to) 原来服务的任务(link[to]) 其他可行的选项
体现了反悔这一增广路的特点
*/

bool dfs(int v)
{
    for(int i = 0; i < vec[v].size(); ++i)
    {
        int to = vec[v][i];
        if(!vis[to])
        {
            vis[to] = 1;
            if(link[to] == -1 || dfs(link[to]))
            {
                link[to] = v;
                return 1;
            }
        }
    }
    return 0;
}

void slove()
{
    int ans = 0;
    memset(link, -1, sizeof(link));
    for(int i = 1; i <= p; ++i)
    {
        memset(vis, 0, sizeof(vis));
        if(dfs(i))
            ans++;
    }
    if(ans == p)
        cout << "YES" << '\n';
    else
        cout << "NO" << '\n';
}

int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        int cnt, tem;
        scanf("%d%d", &p, &n);
        for(int i = 0; i < 1005; ++i)
            vec[i].clear();
        for(int i = 1; i <= p; ++i)
        {
            scanf("%d", &cnt);
            while(cnt--)
            {
                scanf("%d", &tem);
                vec[i].push_back(tem);
            }
        }
        slove();
    }
    return 0;
}

HDU 2063

题意:男女配对

#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

int k, m, n;
int link[1005];
bool vis[1005];
vector<int> vec[1005];

bool dfs(int v)
{
    for(int i = 0; i < vec[v].size(); ++i)
    {
        int to = vec[v][i];
        if(!vis[to])
        {
            vis[to] = 1;
            if(link[to] == -1 || dfs(link[to]))
            {
                link[to] = v;
                return 1;
            }
        }
    }
    return 0;
}

void slove()
{
    int ans = 0;
    memset(link, -1, sizeof(link));
    for(int i = 1; i <= m; ++i)
    {
        memset(vis, 0, sizeof(vis));
        if(dfs(i))
            ans++;
    }
    cout << ans << '\n';
}

int main()
{
    int girl, boy;
    while(~scanf("%d", &k) && k)
    {
        for(int i = 0; i < 1005; ++i)
            vec[i].clear();
        scanf("%d%d", &m, &n);
        for(int i = 0; i < k; ++i)
        {
            scanf("%d%d", &girl, &boy);
            vec[girl].push_back(boy);
        }
        slove();
    }
    return 0;
}

ZOJ 1083 Tokens on the Segments

题意:一个直角坐标轴,y轴上从1到n共n个点,分别对应x轴上一段区间,从对应区间中为每个点匹配一个点,x轴上每个被选择的点不可重复

#include <map>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100005;

int n;
map<int, int> link;
map<int, int> vis;
int l[N], r[N];

bool dfs(int v)
{
    for(int i = l[v]; i <= r[v]; ++i)
        if(!vis[i])
        {
            vis[i] = 1;
            if(link[i] == 0 || dfs(link[i]))
            {
                link[i] = v;
                return 1;
            }
        }
    return 0;
}

void slove()
{
    int ans = 0;
    link.clear();
    for(int i = 1; i <= n; ++i)
    {
        vis.clear();
        if(dfs(i))
            ans++;
    }
    cout << ans << '\n';
}

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i = 1; i <= n; ++i)
            scanf("%d%d", &l[i], &r[i]);
        slove();
    }
    return 0;
}

昨日种种皆成今我:利用一切可利用的时间学习,也不至于不会做,不至于打铁了

今日种种皆成新我:现在不珍惜时间多学多练,将来还是要被碾压、还是要打铁

Site by Baole Zhao | Powered by Hexo | theme PreciousJoy