Codeforces 468B Two Sets(二分图匹配)

题目链接:Codeforces 468B Two Sets

题目大意:给出n个数,要求将n个数分配到两个集合中,集合0中的元素x,要求A-x也再0中,同理1集合。

解题思路:类似二分图匹配的方法。

#include <cstdio>
#include <cstring>
#include <map>
#include <stack>
#include <algorithm>

using namespace std;

const int maxn = 1e5 + 5;

int N, A, B, x[maxn], v[maxn], r = 0;
map<int, int> G;

bool match (int a, int M, int k) {
    int p = G[a];

    if (!G.count(M - a))
        return false;

    int q = G[M - a];

    if (v[q] == -1 || a * 2 == M) {
        v[p] = v[q] = k;
    } else {

        if (match(A + B - 2 * M + a, M, k))
            v[p] = v[q] = k;
        else
            return false;
    }
    return true;
}

bool solve () {
    if (r >= max(A,B))
        return false;

    for (int i = 1; i <= N; i++) {
        if (v[i] != -1)
            continue;

        if (!match(x[i], A, 0) && !match(x[i], B, 1))
            return false;
    }
    return true;
}

int main () {
    scanf("%d%d%d", &N, &A, &B);
    memset(v, -1, sizeof(v));

    for (int i = 1; i <= N; i++) {
        scanf("%d", &x[i]);
        r = max(x[i], r);
        G[x[i]] = i;
    }

    if (solve()) {
        printf("YES\n");
        for (int i = 1; i <= N; i++)
            printf("%d%c", v[i], i == N ? ‘\n‘ : ‘ ‘);
    } else
        printf("NO\n");
    return 0;
}
时间: 2024-11-12 19:44:54

Codeforces 468B Two Sets(二分图匹配)的相关文章

CodeForces 468B Two Sets 二分匹配

把n个数放到集合A和集合B 使得: 对于某个数x,若x在A集合则 a-x也必须在A集合(若a-x不存在于n个数中,则x不能放在A集合) 放在B集合同理. 输出任意解:每个数放在哪个集合里(允许n个数都放一个集合) 思路: 类似二分匹配的做法. [java] view plaincopy import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collecti

Codeforces 468B Two Sets 并查集

题目大意:给出n个数,要求将n个数分配到两个集合中,集合0中的元素x,要求A-x也再0中,同理1集合. 写了几个版本,一直WA在第8组数据...最后参考下ans,写了并查集过了 学到:1.注意离散的逻辑思维,官方答案的 从条件推逆否命题 2.并查集做法:fa[find(i)]=mp[a-p[i]] ? find(a-p[i]) : find(n+2); 3.离散化然后hash的方法,用map时间还是承受得住的,写起来也简单 //#pragma comment(linker, "/STACK:10

[Codeforces 1027 F] Session in BSU [并查集维护二分图匹配问题]

题面 传送门 思路 真是一道神奇的题目呢 题目本身可以转化为二分图匹配问题,要求右半部分选择的点的最大编号最小的一组完美匹配 注意到这里左边半部分有一个性质:每个点恰好连出两条边到右半部分 那么我们可以利用这个性质 考虑一个左边的点和它右边联通的两个点,发现这两个点只能选择一个和这个左边的点匹配 那么我们考虑把这个点点匹配的模型转化成点边匹配 我们在同一个左边点连的两个右边点之间连边,那么问题就变成了一个点和一条相邻的边匹配,求完美匹配的问题了 而这个问题,我们显然可以用并查集来很好的解决 考虑

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

棋盘游戏(二分图匹配)

题目连接: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的棋盘,在格子里放

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中的点连线,他们之间也有一定的容量制约关系(具体看题目中的边权值限制).这样就可以求出最大流量匹配了. 有时我们要求完美匹配,即所有流入的量等于流出的量  . 该题构思极其巧妙,因为我

BZOJ 1191: [HNOI2006]超级英雄Hero(二分图匹配)

云神说他二分图匹配从来都是用网络流水过去的...我要发扬他的精神.. 这道题明显是二分图匹配.网络流的话可以二分答案+最大流.虽然跑得很慢.... ---------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostrea