二分图最大匹配(匈牙利算法) URAL 1721 Two Sides of the Same Coin

题目传送门

 1 /*
 2    题意:三种人,statements,testdata,anthing。要求两个人能完成s和t两个工作,且rank相差2
 3    二分图匹配:此题学习建图技巧,两个集和内部一定没有边相连,rank模4小于2和大于等于2的人才能搭配,并且相差正好2,
 4             两个人会的不能一样。以上条件删选出两个集合,不能按照anthing来分。
 5 */
 6 #include <cstdio>
 7 #include <iostream>
 8 #include <algorithm>
 9 #include <cstring>
10 #include <vector>
11 #include <string>
12 #include <cmath>
13 #include <map>
14 using namespace std;
15 
16 const int MAXN = 1e3 + 10;
17 const int INF = 0x3f3f3f3f;
18 struct Setter
19 {
20     char name[22], can[11];
21     int rk;
22     bool operator < (const Setter &r) const
23     {
24         return rk < r.rk;
25     }
26 }p[MAXN];
27 int svis[MAXN], vis[MAXN];
28 int mp[MAXN];
29 int x[MAXN], y[MAXN];
30 vector<int> G[MAXN];
31 int n, un, vn;
32 
33 bool DFS(int u)
34 {
35     for (int i=0; i<G[u].size (); ++i)
36     {
37         int v = G[u][i];
38         if (!vis[v])
39         {
40             vis[v] = true;
41             if (y[v] == -1 || DFS (y[v]))
42             {
43                 y[v] = u;    x[u] = v;    return true;
44             }
45         }
46     }
47 
48     return false;
49 }
50 
51 void hungary(void)
52 {
53     sort (p+1, p+1+n);  memset (svis, 0, sizeof (svis));
54     un = 0;
55     for (int i=1; i<=n; ++i)
56     {
57         if (svis[i] != 0 || p[i].rk % 4 > 1)    continue;
58         svis[i] = -1;   mp[++un] = i;
59         for (int j=1; j<=n; ++j)
60         {
61             if (svis[j] == -1 || p[j].rk % 4 <= 1)  continue;
62             if (abs (p[i].rk - p[j].rk) != 2)   continue;
63             if (p[i].can[0] == p[j].can[0] && p[i].can[0] != 'a')   continue;
64             svis[j] = 1;    G[un].push_back (j);
65         }
66     }
67 
68     int res = 0;    memset (x, -1, sizeof (x));    memset (y, -1, sizeof (y));
69     for (int i=1; i<=un; ++i)
70     {
71         memset (vis, false, sizeof (vis));
72         if (DFS (i))    res++;
73     }
74     
75     printf ("%d
", res);
76     for (int i=1; i<=un; ++i)
77     {
78         if (x[i] == -1) continue;
79         int id1 = mp[i], id2 = x[i];
80         if (p[id1].can[0] == 't' || p[id2].can[0] == 's')   swap (id1, id2);
81         printf ("%s %s
", p[id1].name, p[id2].name);
82     }
83 }
84 
85 int main(void)      //URAL 1721 Two Sides of the Same Coin 
86 {
87     //freopen ("K.in", "r", stdin);
88 
89     scanf ("%d", &n);
90     for (int i=1; i<=n; ++i)
91     {
92         scanf ("%s %s %d", p[i].name, p[i].can, &p[i].rk);
93     }
94 
95     hungary ();
96     
97     return 0;
98 }
编译人生,运行世界!
原文地址:https://www.cnblogs.com/Running-Time/p/4657119.html