[二分匹配]URAL1721Two Sides of the Same Coin

题意:给n个人,每个人都有3个参数,分别是名字,能做的事(a:statements  b:testdate  a、b都可以:anything),Rank

要求:一个人只能做一个事件,要两个人Rank相差2才能共同做a、b,问最多能做多少个a、b,并输出 做a人的名字  做b人的名字

很明显是二分匹配 稳定婚姻问题。

一开始按照 能做a的人->能做b的人 建图  怎么都过不了案例。。。

后来发现若是这样建图,对于

1 ab 4

2  a  2         

3  b  6

若是这样建图    

那么就会有两个匹配:1和3  以及  2和1

为什么不是一个匹配呢?

因为对于稳定婚姻而言 男的 女的 都分别有编号为1到n的人

因此1和3  以及  2和1的含义 (若用这样的建图 用稳定婚姻来解释的话 就是) 1号男人和3号女人  以及  2号男人以及1号女人 <这样看来确实两对>

而对于这个题目 很显然 男女是共用一个编号的

 若是按a->b这样建图  实际上来说 并没有“二分”

那么要怎么建图呢?

此题一共就俩限制一个是a->b,另一个是Rank之差为2。那么既然不是前一个,那必定是后一个咯~

所以二分的方法就是:

Rank相差2的不能在同一个集合里

  比如Rank为2的为男  那么Rank为4的就要是女的  Rank为6的为男  那么Rank为8的就要是女

那这样分的话  要是规定Rank 6为女(即限制了4为男), 若之前已经规定了Rank 2为男(即限制了4为女)  那不就矛盾了吗?

于是先按照Rank来排个序 再来确定男女两个集合就没问题了~

给一个案例:

6
a anything 2
b anything 4
c anything 4
d anything 4
e anything 6
f anything 6

代码:(因为是比赛中写的 所以巨丑...)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 struct node
 4 {
 5     string name;
 6     bool a, b;
 7     int Rank;
 8 }a[5005];
 9 bool cmp(node a, node b)
10 {
11     return a.Rank<b.Rank;
12 }
13 vector<int> v[5005];
14 int lef[5005];
15 bool t[5005];
16 int n;
17 int fa[5005];
18 bool match(int x)
19 {
20     for(int i=0;i<(int)v[x].size();i++)
21         if(t[v[x][i]]==0)
22         {
23             t[v[x][i]]=1;
24             if(lef[v[x][i]]==-1 || match(lef[v[x][i]]))
25             {
26                 fa[x]=-1, fa[fa[x]]=-1;
27                 fa[v[x][i]]=x, fa[x]=v[x][i];
28                 lef[v[x][i]]=x;
29                 return true;
30             }
31         }
32     return false;
33 }
34 int solve()
35 {
36     int ans=0;
37     memset(lef, -1, sizeof(lef));
38     memset(fa, -1, sizeof(fa));
39     for(int i=1;i<=n;i++)
40         if(v[i].size())
41         {
42             memset(t, 0, sizeof(t));
43             if(match(i))
44                 ans++;
45         }
46     return ans;
47 }
48 bool vis[5005];
49 bool zz[5005];
50 int main()
51 {
52     scanf("%d", &n);
53     for(int i=1;i<=n;i++)
54     {
55         string s;
56         cin>>a[i].name>>s;
57         if(s=="anything")
58             a[i].a=1, a[i].b=1;
59         else if(s=="statements")
60             a[i].a=1, a[i].b=0;
61         else
62             a[i].a=0, a[i].b=1;
63         scanf("%d", &a[i].Rank);
64     }
65     for(int i=0;i<=n;i++)
66         v[i].clear();
67     sort(a+1, a+n+1, cmp);
68     memset(zz, 0, sizeof(zz));
69     for(int i=1;i<=n;i++)
70     {
71         if(zz[a[i].Rank-2])
72             continue;
73         zz[a[i].Rank]=1;
74     }
75     for(int i=1;i<=n;i++)
76         for(int j=i+1;j<=n;j++)
77             if(abs(a[i].Rank-a[j].Rank)==2)
78                 if((a[i].a==1 && a[j].b==1) || (a[i].b==1 && a[j].a==1))
79                 {
80                     if(zz[a[i].Rank])
81                         v[i].push_back(j);
82                     else if(zz[a[j].Rank])
83                         v[j].push_back(i);
84                 }
85     printf("%d
", solve());
86     memset(vis, 0, sizeof(vis));
87     for(int i=1;i<=n;i++)
88         if(fa[i]!=-1 && fa[fa[i]]==i && !vis[i] && !vis[fa[i]])
89         {
90             if(a[i].b==1 && a[fa[i]].a==1)
91                 cout<<a[fa[i]].name<<" "<<a[i].name<<endl;
92             else
93                 cout<<a[i].name<<" "<<a[fa[i]].name<<endl;
94             vis[i]=1, vis[fa[i]]=1;
95         }
96     return 0;
97 }
URAL 1721
原文地址:https://www.cnblogs.com/Empress/p/4321952.html