[HNOI2006]超级英雄Hero [Scoi2010]游戏 匈牙利算法 解题报告

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33468963/article/details/69397460

题目:
http://www.lydsy.com/JudgeOnline/problem.php?id=1191
http://www.lydsy.com/JudgeOnline/problem.php?id=1854

这两道题是极为类似的,只是一道 n <1001,另一道 n <10000 好像区别不大
你有n个物品,每个物品有两个值且每个物品只能使用一次,每次使用可以选择它的其中一个值。
提问:使用一些物品后,能取到的最大的连续值是多少?

以 [HNOI2006]超级英雄Hero 为例:有六个物品,其对应值分别是
3 2
2 0
0 3
0 4
3 2
3 2
当分别选择<3,2,0,4>可过前四关,且这也是最优解(之一)

此时可选物品和对应值形成了一个 “二分图”

二分图匹配——匈牙利算法

匈牙利算法的基本内容是:为该点寻找一个匹配,并且其他已匹配点仍有匹配
定义一个bool f(v) ,v 指新的匹配点,返回能否匹配成功。
先枚举v的每一个未在递归过程中被搜索过的节点,如果其未被匹配,则匹配,否则调用f(其连接节点)以重新分配。

核心代码:

bool f(int v) {
    for (int i=0;i<u[v].size();i++)
    if (!vis[rt = u[v][i]]) {
        vis[rt] = true;
        if ((!q[rt]) || f(q[rt])) return q[rt] = v;
    } return false;
}

[HNOI2006]超级英雄Hero :

#include <cstdio>
#include <cstring>
#include <vector>

int n,m,i,q[1010],rt,t1,t2;
bool vis[1010];
std::vector <int> u[1010];

bool f(int v) {
    for (int i=0;i<u[v].size();i++)
    if (!vis[rt = u[v][i]]) {
        vis[rt] = true;
        if ((!q[rt]) || f(q[rt])) return q[rt] = v;
    } return false;
}

int main() {
    scanf("%d%d",&n,&m);
    for (i=1;i<=m;i++) {
        scanf("%d%d",&t1,&t2);
        u[i].push_back(t1);  u[i].push_back(t2);
    }
    for (i=1;i<=m;i++) if (memset(vis,0,sizeof(vis)) && !f(i)) break;
    printf("%d\n",i - 1);
}

[Scoi2010]游戏:(这题memset会超时 于是开int vis[]记录)

#include <cstdio>
#include <cstring>

int n,i,q[1000010],head[1000010],last[1000010],rt,t1,t2,ans,num;
int vis[1000010],id;
struct ljb {int to,nxt;} u[2000010];

bool f(int v) {
    for (int i=head[v];i;i=u[i].nxt) if (vis[rt = u[i].to] ^ id) {
        vis[rt] = id;
        if ((!q[rt]) || f(q[rt])) return q[rt] = v;
    } return false;
}

int main() {
    for (scanf("%d",&n),i=1;i<=n;i++) {
        scanf("%d%d",&t1,&t2);
        u[++num].to = i;  last[t1] = last[t1] ? u[last[t1]].nxt = num : head[t1] = num;
        u[++num].to = i;  last[t2] = last[t2] ? u[last[t2]].nxt = num : head[t2] = num;
    } while (f(id = ++ans));
    printf("%d\n",ans - 1);
}

猜你喜欢

转载自blog.csdn.net/qq_33468963/article/details/69397460