您的位置:首页 > 其它

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

2015-07-18 16:14 447 查看
题目传送门

 /*
题意:三种人,statements,testdata,anthing。要求两个人能完成s和t两个工作,且rank相差2
二分图匹配:此题学习建图技巧,两个集和内部一定没有边相连,rank模4小于2和大于等于2的人才能搭配,并且相差正好2,
两个人会的不能一样。以上条件删选出两个集合,不能按照anthing来分。
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <cmath>
#include <map>
using namespace std;

const int MAXN = 1e3 + 10;
const int INF = 0x3f3f3f3f;
struct Setter
{
char name[22], can[11];
int rk;
bool operator < (const Setter &r) const
{
return rk < r.rk;
}
}p[MAXN];
int svis[MAXN], vis[MAXN];
int mp[MAXN];
int x[MAXN], y[MAXN];
vector<int> G[MAXN];
int n, un, vn;

bool DFS(int u)
{
for (int i=0; i<G[u].size (); ++i)
{
int v = G[u][i];
if (!vis[v])
{
vis[v] = true;
if (y[v] == -1 || DFS (y[v]))
{
y[v] = u;    x[u] = v;    return true;
}
}
}

return false;
}

void hungary(void)
{
sort (p+1, p+1+n);  memset (svis, 0, sizeof (svis));
un = 0;
for (int i=1; i<=n; ++i)
{
if (svis[i] != 0 || p[i].rk % 4 > 1)    continue;
svis[i] = -1;   mp[++un] = i;
for (int j=1; j<=n; ++j)
{
if (svis[j] == -1 || p[j].rk % 4 <= 1)  continue;
if (abs (p[i].rk - p[j].rk) != 2)   continue;
if (p[i].can[0] == p[j].can[0] && p[i].can[0] != 'a')   continue;
svis[j] = 1;    G[un].push_back (j);
}
}

int res = 0;    memset (x, -1, sizeof (x));    memset (y, -1, sizeof (y));
for (int i=1; i<=un; ++i)
{
memset (vis, false, sizeof (vis));
if (DFS (i))    res++;
}

printf ("%d\n", res);
for (int i=1; i<=un; ++i)
{
if (x[i] == -1) continue;
int id1 = mp[i], id2 = x[i];
if (p[id1].can[0] == 't' || p[id2].can[0] == 's')   swap (id1, id2);
printf ("%s %s\n", p[id1].name, p[id2].name);
}
}

int main(void)      //URAL 1721 Two Sides of the Same Coin
{
//freopen ("K.in", "r", stdin);

scanf ("%d", &n);
for (int i=1; i<=n; ++i)
{
scanf ("%s %s %d", p[i].name, p[i].can, &p[i].rk);
}

hungary ();

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: