luogu2763 试题库问题 二分匹配

时间:2022-07-01 06:11:08

关键词:二分匹配

本题用有上下界的网络流可以解决,但编程复杂度有些高。

每个类需要多少题,就设置多少个类节点。每个题节点向其所属的每一个类节点连一条边。这样就转化成了二分匹配问题。

#include <cstdio>
#include
<cmath>
#include
<algorithm>
#include
<cstring>
#include
<cassert>
using namespace std;

#define LOOP(i,n) for(int i=1; i<=n; i++)
const int MAX_X = 1010, MAX_Y = 1010, MAX_EDGE = MAX_X*MAX_Y;

struct Hungary
{
struct Xnode;
struct Ynode;
struct Edge;

struct Xnode
{
Edge
*Head;
int Id;
}_xNodes[MAX_X];
int _xCnt;

struct Ynode
{
Xnode
*Match;
bool Vis;
Ynode():Vis(
false){}
}_yNodes[MAX_Y];
int _yCnt;

struct Edge
{
Xnode
*X;
Ynode
*Y;
Edge
*Next;
Edge(Xnode
*x, Ynode *y, Edge *next):X(x),Y(y),Next(next){}
}
*_edges[MAX_EDGE];
int _eCnt;

void Init(int xCnt, int yCnt)
{
_xCnt
= xCnt;
_yCnt
= yCnt;
_eCnt
= 0;
}

void Build(int xId, int yId)
{
//printf("xId %d yId %d\n", xId, yId);
Xnode *x = xId + _xNodes;
Ynode
*y = yId + _yNodes;
x
->Id = xId;
Edge
*e = _edges[++_eCnt] = new Edge(x, y, x->Head);
x
->Head = e;
}

bool Dfs(Xnode *x)
{
for (Edge *e = x->Head; e; e = e->Next)
{
if (!e->Y->Vis)
{
e
->Y->Vis = true;
if (!e->Y->Match || Dfs(e->Y->Match))
{
e
->Y->Match = x;
return true;
}
}
}
return false;
}

int GetMatchCnt()
{
int ans = 0;
LOOP(xId, _xCnt)
{
LOOP(yId, _yCnt)
_yNodes[yId].Vis
= false;
ans
+= Dfs(xId + _xNodes);
}
return ans;
}
}g;

int main()
{
#ifdef _DEBUG
freopen(
"c:\\noi\\source\\input.txt", "r", stdin);
#endif
int totSort, totQuest, sortNeedCnt[MAX_X], sortPrevCnt[MAX_Y], yCnt = 0, matchCnt;
memset(sortPrevCnt,
0, sizeof(sortPrevCnt));
memset(sortNeedCnt,
0, sizeof(sortNeedCnt));
scanf(
"%d%d", &totSort, &totQuest);
LOOP(i, totSort)
{
scanf(
"%d", i + sortNeedCnt);
sortPrevCnt[i
+ 1] = (yCnt += sortNeedCnt[i]);
}
g.Init(totQuest, yCnt);
LOOP(xId, totQuest)
{
int sortInCnt;
scanf(
"%d", &sortInCnt);
LOOP(i, sortInCnt)
{
int sortIn;
scanf(
"%d", &sortIn);
LOOP(j, sortNeedCnt[sortIn])
g.Build(xId, j
+ sortPrevCnt[sortIn]);
}
}
matchCnt
= g.GetMatchCnt();
if (matchCnt < yCnt)
{
printf(
"No Solution!\n");
return 0;
}
LOOP(curSort, totSort)
{
printf(
"%d: ", curSort);
for (int yId = sortPrevCnt[curSort] + 1; yId <= sortPrevCnt[curSort] + sortNeedCnt[curSort]; yId++)
printf(
"%d ", g._yNodes[yId].Match->Id);
printf(
"\n");
}
return 0;
}