zoj - 2362 - Beloved Sons(二分图最大匹配)

题意:国王对其N个 (1 <= N <= 400)儿子各有一个喜欢度,有N个美女,N个儿子喜欢美女中的一些,国王的幸福感 = 对可以成婚的儿子的喜欢度 ^ 2 的和,问国王最幸福时,儿子的对象情况。

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2362

——>>男、女,很像二分图吧。。

要使平方和最大,可转化为要使和最大。。

将儿子按国王对他们的喜欢度从高到低排序,再依次进行匹配对象,因为在求增广路的时候,不会使已匹配上的点丢失,所以二分图最大匹配国王幸福感最大时的匹配。。(会不会国王喜欢度高的儿子先匹配了导致后面的儿子抢不到该对象而使国王的幸福感不是最高呢?不会,因为一个美女最多只归一个儿子,如果没有增广路,那么先得到的儿子总使国王更幸福。。

#include <cstdio>
#include <cstring>
#include <algorithm>

using std::sort;

const int MAXN = 400 + 10;

struct PERSON
{
    int id;
    int val;

    bool operator < (const PERSON& e) const
    {
        return val > e.val;
    }
} son[MAXN];

struct EDGE
{
    int to;
    int nxt;
} edge[MAXN * MAXN * 2];

bool vis[MAXN << 1];
int N;
int ecnt, hed[MAXN << 1];
int fa[MAXN << 1];
int pto[MAXN];

void Init()
{
    ecnt = 0;
    memset(hed, -1, sizeof(hed));
}

void AddEdge(int u, int v)
{
    edge[ecnt].to = v;
    edge[ecnt].nxt = hed[u];
    hed[u] = ecnt++;
}

void Read()
{
    int cnt, girlson;

    scanf("%d", &N);
    for (int i = 1; i <= N; ++i)
    {
        scanf("%d", &son[i].val);
        son[i].id = i;
    }
    sort(son + 1, son + 1 + N);
    for (int i = 1; i <= N; ++i)
    {
        pto[son[i].id] = i;
    }
    for (int i = 1; i <= N; ++i)
    {
        scanf("%d", &cnt);
        for (int j = 1; j <= cnt; ++j)
        {
            scanf("%d", &girlson);
            AddEdge(pto[i], N + girlson);
        }
    }
}

bool Match(int u)
{
    for (int e = hed[u]; e != -1; e = edge[e].nxt)
    {
        int v = edge[e].to;
        if (!vis[v])
        {
            vis[v] = true;
            int temp = fa[v];
            fa[v] = u;
            if(temp == -1 || Match(temp)) return true;
            fa[v] = temp;
        }
    }

    return false;
}

void Solve()
{
    int ret[MAXN];

    memset(fa, -1, sizeof(fa));
    for (int i = 1; i <= N; ++i)
    {
        memset(vis, 0, sizeof(vis));
        Match(i);
    }

    memset(ret, 0, sizeof(ret));
    for (int i = N + 1; i <= N + N; ++i)
    {
        if (fa[i] != -1)
        {
            ret[son[fa[i]].id] = i - N;
        }
    }

    for (int i = 1; i < N; ++i)
    {
        printf("%d ", ret[i]);
    }
    printf("%d\n", ret[N]);
}

int main()
{
    int T;

    scanf("%d", &T);
    while (T--)
    {
        Init();
        Read();
        Solve();
    }

    return 0;
}
时间: 2024-10-11 17:54:58

zoj - 2362 - Beloved Sons(二分图最大匹配)的相关文章

ZOJ 1364 Machine Schedule(二分图最大匹配)

题意 机器调度问题 有两个机器A,B A有n种工作模式0...n-1 B有m种工作模式0...m-1 然后又k个任务要做 每个任务可以用A机器的模式i或b机器的模式j来完成 机器开始都处于模式0 每次换模式时都要重启 问完成所有任务机器至少重启多少次 最基础的二分图最大匹配问题 对于每个任务把i和j之间连一条边就可以构成一个二分图 那么每个任务都可以对应一条边 那么现在就是要找最少的点 使这些点能覆盖所有的边 即点覆盖数 又因为二分图的点覆盖数 = 匹配数 那么就是裸的求二分图最大匹配问题了 两

ZOJ 1654 - Place the Robots (二分图最大匹配)

题意:在一个m*n的地图上,有空地,草和墙,其中空地和草能穿透攻击光线,而墙不能.每个机器人能够上下左右攻击,问在地图上最多能放多少个不互相攻击的机器人. 这个题和HDU 1045 -  Fire Net很像.很容易联想到对每个点编号然后互相攻击的点连边再求图的最大独立集,但是这个题数据量太多,超时. 换个思路. 将每个机器人可以攻击到的区域在横和竖方向上分开,这样当横和竖攻击方向都确定时就可以确定一个机器人的放置位置,而在同一个横或竖的攻击区域内不可以再放置机器人. 这样我们把原图上的空地按照

ZOJ 1654 Place the Robots 二分图最大匹配

唉,又是神一样的建模,表示完全想不到. 题意是给你一块地,上面有空地,草地,障碍三种地形,然后让你在上面放机器人,机器人只能放在空地上.机器人会向上下左右四个方向发出攻击,机器人的攻击可以穿过草地但是无法穿过障碍.问你在不会是机器人相互攻击的前提下,最多能放多少个机器人. 我觉得大致的思路应该是这样的,首先会想当然的想到把能够相互攻击到的空地连边,然后求最大独立集,但最大独立集不好求,所以要想办法把它转化成最大匹配问题. 所以要想办法把空地变成边,首先一块空地肯定是有他的横坐标和纵坐标,可以表示

匈牙利算法dfs模板 [二分图][二分图最大匹配]

最近学了二分图最大匹配,bfs模板却死活打不出来?我可能学了假的bfs 于是用到了dfs模板 寻找二分图最大匹配的算法是匈牙利算法 匈牙利算法的主要程序是寻找增广路 寻找增光路是过程是:从一个未经配对的点出发,历经未配边.匹配边.未配边.匹配边.未配边....最终到达一个未配点的过程,只要把路径中的未配边和匹配边的“身份”对调,匹配就加一了.这就是一个寻找增广路的过程,通过不断寻找增广路,可以找到最大的匹配. 1 #include<cstdio> 2 #include<cstring&g

图论——LCA、强联通分量、桥、割顶、二分图最大匹配、网络流

A: 交通运输线 时间限制: 5 Sec  内存限制: 128 MB 题目描述 战后有很多城市被严重破坏,我们需要重建城市.然而,有些建设材料只能在某些地方产生.因此,我们必须通过城市交通,来运送这些材料的城市.由于大部分道路已经在战争期间完全遭到破坏,可能有两个城市之间没有道路.当然在运输线中,更不可能存在圈. 现在,你的任务来了.给你战后的道路情况,我们想知道,两个城市之间是否存在道路,如果存在,输出这两个城市之间的最短路径长度. 输入 第一行一个整数Case(Case<=10)表示测试数据

POJ 2226二分图最大匹配

匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是二部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图最大匹配的算法. #include<stdio.h> #include<string.h> #include<stdlib.h> int n1,n2; char map[1005][1005]; //数组开大点 int mapx[1005][1005],mapy[1005]

【Codevs1922】骑士共存问题(最小割,二分图最大匹配)

题意: 在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入. 对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击. n<=200,m<=n^2 思路:经典的二分图最大匹配问题,采用黑白点染色的思想. 如果按照相邻点黑白不同染色,可以发现每次跳到的点必定与现在所在点不同色,二分图最大匹配即可. 这里用最小割来解决,因为不能允许任何黑白点之间的任何一条边有流量,符合最小割的思想. 1

POJ2239 Selecting Courses(二分图最大匹配)

题目链接 N节课,每节课在一个星期中的某一节,求最多能选几节课 好吧,想了半天没想出来,最后看了题解是二分图最大匹配,好弱 建图: 每节课 与 时间有一条边 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 #include <algorithm> 6 #include <vector> 7 using namespa

二分图最大匹配总结

hdoj1528 二分匹配模版: 代码: 1 #include<stdio.h> 2 #include<iostream> 3 #include<string.h> 4 #include<algorithm> 5 #include<math.h> 6 using namespace std; 7 #define N 220 8 9 int n, maps[N][N], vis[N], used[N]; 10 11 struct node 12 {