二分图匹配。不过这里要暴力枚举每一天的情况。
/*******************************************************************************
# Author : Neo Fung
# Email : neosfung@gmail.com
# Last modified: 2012-05-23 20:59
# Filename: ZOJ3277 POJ3836 HDU3269 P2P File Sharing System.cpp
# Description :
******************************************************************************/
#ifdef _MSC_VER
#define DEBUG
#define _CRT_SECURE_NO_DEPRECATE
#endif
#include <fstream>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <string>
#include <limits.h>
#include <algorithm>
#include <math.h>
#include <numeric>
#include <functional>
#include <ctype.h>
#define MAX 110
using namespace std;
bool map[MAX][MAX]; //邻接矩阵
bool used[MAX]; //在每次找增广路径中用于记录当前节点是否在增广路径中
int mat[MAX]; //各个节点对应的匹配项
int m,n,beg[MAX],end[MAX];
bool task[MAX*MAX];
bool find(const int &x) //从x开始是否有增广路
{
int i;
for(i=1;i<=8;++i)
{
if(map[x][i] && !used[i]) //若x与i有边相连且i不在当前的增广路上
{
used[i]=1;
if(!mat[i] || find(mat[i])) //若i没有匹配项或从i的匹配项开始有增广路
{
mat[i]=x;
return true;
}
}
}
return false;
}
int main(void)
{
#ifdef DEBUG
freopen("../stdin.txt","r",stdin);
freopen("../stdout.txt","w",stdout);
#endif
int tmp,var,ncase=1;
scanf("%d",&ncase);
while(ncase--)
{
scanf("%d",&n);
memset(map,0,sizeof(map));
memset(task,0,sizeof(task));
m=0;
int finish=0,start=INT_MAX;
for(int i=1;i<=n;++i)
{
scanf("%d%d%d",&beg[i],&end[i],&var);
finish=max(finish,end[i]);
start=min(start,beg[i]);
while(var--)
{
scanf("%d",&tmp);
map[i][tmp]=1;
}
}
bool ans=true;
for(int i=start;i<=finish && ans;++i)
{
memset(mat,0,sizeof(mat));
for(int j=1;j<=n && ans;++j)
if(beg[j]<=i && end[j]>=i)
{
memset(used,0,sizeof(used));
if(!find(j))
ans=false;
}
}
if(ans)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}