SGU 210. Beloved Sons(二分图匹配)

题目链接:点击打开链接

思路:因为每一个左边的匹配点都有一个优先级, 所以我们按照左边的点的优先级排序, 这样就会优先匹配前面的点。 原因很简单 , 我们只要知道匈牙利算法是怎么进行的就可以了:  我们依次枚举每一个左边的点, 对于一个左边点x, 找到一个右边点y, 如果y没有被匹配, 那么(x, y)就是一对新匹配, 如果y已经匹配了x`, 那么我们尝试为x`重新找一个匹配点, 如果找到了那么(x,y)同样是一对新增的匹配。  所以,对于左边的一个x,如果它之前已经被匹配, 那么无论后面如何, 它还是被匹配的。 所以此题就没有什么可说的了。

细节参见代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const double eps = 1e-6;
const double PI = acos(-1);
const int mod = 1000000000 + 7;
const int INF = 0x3f3f3f3f;
const int seed = 131;
const ll INF64 = ll(1e18);
const int maxn = 500;
int T,n,m,use[maxn], from[maxn], tot = 0;
struct node {
    int id, v;
    bool operator < (const node& rhs) const {
        return v > rhs.v;
    }
}a[maxn];
vector<int> g[maxn];
bool match(int x) {
    int len = g[x].size();
    for(int i = 0; i < len; i++)
    if(!use[g[x][i]]) {
        use[g[x][i]] = true;
        if(from[g[x][i]] == -1 || match(from[g[x][i]])) {
            from[g[x][i]] = x;
            return true;
        }
    }
    return false;
}
int hungary(int n) {
    tot = 0;
    memset(from, -1, sizeof(from));
    for(int i = 1; i <= n; i++) {
        memset(use, 0, sizeof(use));
        if(match(a[i].id)) ++tot;
    }
    return tot;
}
int ans[maxn];
int k, v;
int main() {
    while(~scanf("%d",&n)) {
        for(int i = 1; i <= n; i++) {
            scanf("%d",&a[i].v);
            ans[i] = 0;
            a[i].id = i;
        }
        for(int i = 1; i <= n; i++) {
            scanf("%d",&k);
            g[i].clear();
            for(int j = 1; j <= k; j++) {
                scanf("%d",&v);
                g[i].push_back(v);
            }
        }
        sort(a+1, a+n+1);
        int cur = hungary(n);
        for(int i = 1; i <= n; i++) {
            if(from[i] == -1) ;
            else {
                ans[from[i]] = i;
            }
        }
        for(int i = 1; i <= n; i++) {
            printf("%d%c", ans[i], i == n ? '\n' : ' ');
        }
    }
    return 0;
}
时间: 2024-08-05 08:13:16

SGU 210. Beloved Sons(二分图匹配)的相关文章

SGU 210 ~ 219

点击标题查看代码 210. Beloved Sons 题意:国王要给王子们安排婚事,每个王子都有一个权重Ai,目标是使所有与心爱女孩结婚的王子们的权重的2范数最大. 二分图匹配即可,因为匈牙利算法的贪心性质,会使排在前面的王子先找到配偶,这样,如果后面有王子无法匹配,一定是与前面的王子发生冲突,但是如果修改的话,答案不会更优. 211. Strange Counter 题意:给定一个counter表示数的方法如下 A[N-1] * 2^(N-1) + A[N-2] * 2^(N-2) + ...

棋盘游戏(二分图匹配)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1281 棋盘游戏 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3200    Accepted Submission(s): 1897 Problem Description 小 希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放

hdu1853 Cyclic Tour (二分图匹配KM)

Cyclic Tour Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others)Total Submission(s): 1688    Accepted Submission(s): 859 Problem Description There are N cities in our country, and M one-way roads connecting them. Now Li

poj1904 二分图匹配+强连通分量

http://poj.org/problem?id=1904 Description Once upon a time there lived a king and he had N sons. And there were N beautiful girls in the kingdom and the king knew about each of his sons which of those girls he did like. The sons of the king were you

[SOJ611] 排序【二分图匹配】

题意简述:有一个\(n\times m\)的矩阵\(a\),\([1, n\cdot m]\)的整数恰好在其中出现一次.我们需要执行以下三次操作: 将\(a\)的每一行\(m\)个数任意变换顺序,得到矩阵\(b\). 将\(b\)的每一列\(n\)个数任意变换顺序,得到矩阵\(c\). 将\(c\)的每一行\(m\)个数任意变换顺序,得到矩阵\(d\). 其中,矩阵\(d\)满足\(d_{i, j}=(i-1)\cdot m+j\).要求输出矩阵\(b\)和\(c\).\(1\leq n, m\

POJ2584 T-Shirt Gumbo 二分图匹配(网络流)

1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 const int inf=0x3f3f3f3f; 6 const int sink=30; 7 8 struct Edge 9 { 10 int to; 11 int next; 12 int capacity; 13 14 void assign(int t,int n,int c) 15 { 16 to=t; next=n; ca

BZOJ 1854 游戏(二分图匹配或并查集)

此题的二分图匹配做法很容易想,就是把属性当做s集,武器当做t集,如果该武器拥有该武器则连一条边. 那么答案就是求该二分图的最大前i个匹配.将匈牙利算法改一改,当前找不到增广路就break. 但是过这个题需要常数优化,不能每次都fillchar一遍used数组.可以用队列将使用的used点加入,然后需要初始化的时候弹出即可. # include <cstdio> # include <cstring> # include <cstdlib> # include <i

HDU 3081:Marriage Match II(二分图匹配+并查集)

http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意:有n个男生n个女生,他们只有没有争吵或者女生a与男生A没有争吵,且女生b与女生a是朋友,因此女生b也可以和男生A过家家(具有传递性).给出m个关系,代表女生a和男生b没有争吵过.给出k个关系,代表女生a与女生b是好朋友.每一轮过家家之后,女生只能选择可以选择并且没选过的男生过家家,问游戏能进行几轮. 思路:因为n<=100,因此支持O(n^3)的算法,挺容易想到是一个二分图匹配的.(出现在我的网络

11082 - Matrix Decompressing (网络流建模|二分图匹配)

该题是一道经典的二分图匹配的题目 .现在终于有点明白什么是二分图匹配了,其实说白了就是依赖于最大流算法之上的一种解决特定问题的算法 . 所谓二分图,就是我们假定有两个集合A和B,每个集合中有若干元素(点),其中源点与A相连,汇点与B相连,并且他们的总容量决定了最终答案的上限,所以一定要维护好 . 然后由A中的点向B中的点连线,他们之间也有一定的容量制约关系(具体看题目中的边权值限制).这样就可以求出最大流量匹配了. 有时我们要求完美匹配,即所有流入的量等于流出的量  . 该题构思极其巧妙,因为我