[二分匹配]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

若是这样建图    [二分匹配]URAL1721Two Sides of the Same Coin

那么就会有两个匹配: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

 

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

[二分匹配]URAL1721Two Sides of the Same Coin
 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\n", 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

 

你可能感兴趣的:(ide)