题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3729
题意:有n个学生,他们没有告诉老师自己的分数,只是说了自己的排位区间,即从xi到yi,但是有些学生说了谎,现在问你那些学生说了实话,由于有多种可能,让你输出字典序最大的
解析:也就是求二分图匹配,从顶点编号最大的开始找增广路,这样能保证字典序最大
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+300;
const int maxm = 61*maxn;
struct node
{
int to,next;
}edges[maxm];
int head[maxn],cnt;
int match[maxn],vis[maxn];
void init()
{
memset(head,-1,sizeof(head));
memset(match,0,sizeof(match));
memset(vis,0,sizeof(vis));
cnt = 0;
}
void addEdge(int from,int to)
{
edges[cnt].to = to;
edges[cnt].next = head[from];
head[from] = cnt++;
}
bool dfs(int u)
{
for(int i=head[u];i!=-1;i = edges[i].next)
{
int v = edges[i].to;
if(vis[v]) continue;
vis[v] = 1;
if(!match[v] || dfs(match[v]))
{
match[v] = u;
match[u] = v;
return true;
}
}
return false;
}
int main(void)
{
int t,n;
scanf("%d",&t);
while(t--)
{
init();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int x,y;
scanf("%d %d",&x,&y);
for(int j=x;j<=y;j++)
addEdge(i,j+n);
}
vector<int>ans;
for(int i=n;i>=1;i--)
{
memset(vis,0,sizeof(vis));
if(dfs(i))
ans.push_back(i);
}
printf("%d\n",ans.size());
for(int i=ans.size()-1;i>=0;i--)
{
if(i==0)printf("%d\n",ans[i]);
else
printf("%d ",ans[i]);
}
}
return 0;
}