关键词:二分匹配
本题用有上下界的网络流可以解决,但编程复杂度有些高。
每个类需要多少题,就设置多少个类节点。每个题节点向其所属的每一个类节点连一条边。这样就转化成了二分匹配问题。
#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;
}