cf Two Sets (我用二分最大匹配做的)

来源:互联网 发布:php json 中括号 编辑:程序博客网 时间:2024/05/17 06:03

题意:

n个数p1,p2....pn     两个数a,b

把它们分成A,B两个集合。

若x属于A,a-x一定属于A。

若x属于B,b-x一定属于B。

问是否可能将这n个数分成两个集合。若可以,输出每个数是属于A集合还是B集合(0:集合A,1:集合B)


思路:

这题我用二分图最大匹配做的。他们用并查集,额.. 一开始就没想过并查集哩,回头再看看并查集的思路吧。

若x属于A,则a-x属于A。若a-x属于A,则x属于A。集合B同理。

两两配对,若x和y可以装进一个集合,则将它们之间连条线。然后二分图最大匹配看匹配数是否等于n。

开始时用map记录p[i]这个数在数组中的位置

剩下看代码啦,易懂


代码:

#include <cstdio>#include <iostream>#include <string.h>#include <cstdlib>#include <algorithm>#include <queue>#include <vector>#include <cmath>#include <map>#include <stack>using namespace std;int const uu[4] = {1,-1,0,0};int const vv[4] = {0,0,1,-1};typedef long long ll;int const maxn = 50005;int const inf = 0x3f3f3f3f;ll const INF = 0x7fffffffffffffffll;double eps = 1e-10;double pi = acos(-1.0);#define rep(i,s,n) for(int i=(s);i<=(n);++i)#define rep2(i,s,n) for(int i=(s);i>=(n);--i)#define mem(v,n) memset(v,(n),sizeof(v))#define lson l, m, rt<<1#define rson m+1, r, rt<<1|1int n,a,b;int p[100005];vector<int> graph[100005];bool bmask[100005];int cx[100005], cy[100005];int findPath(int u){    int L = graph[u].size();    rep(i,0,L-1) if(!bmask[graph[u][i]]){        bmask[graph[u][i]] = true;        if(cy[graph[u][i]]==-1 || findPath(cy[graph[u][i]])){            cy[graph[u][i]] = u;            cx[u] = graph[u][i];            return 1;        }    }    return 0;}int MaxMatch(){    int ans = 0;    rep(i,1,n) cx[i] = cy[i ] = -1;    rep(i,1,n) if(cx[i]==-1){        mem(bmask,false);        ans += findPath(i);    }    return ans;}int main(){    map<int,int> mp;    scanf("%d%d%d",&n,&a,&b);    rep(i,1,n){        scanf("%d",&p[i]);        mp[p[i]] = i;    }    rep(i,1,n){        if(mp[a-p[i]])            graph[i].push_back(mp[a-p[i]]);        if(mp[b-p[i]])            graph[i].push_back(mp[b-p[i]]);    }    int dd = MaxMatch();    if(dd!=n) printf("NO\n");    else{        printf("YES\n");        rep(i,1,n){            if(p[i]+p[cx[i]]==a) printf("0 ");            else printf("1 ");        }        printf("\n");    }}


0 0
原创粉丝点击