题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3729
题意:一共有N个点,每一个点分别对应一个区间里任意一个数,要求出所有可以匹配的点
思路:刚开始以为是区间贪心,按照其左区间进行了排序进行贪心,wa了几次,但是并没有发现哪里错了……后来看了别人的题解,发现是利用二分图照增广路来进行匹配,有多个答案要输出字典序最大的序列,匈牙利算法的时间复杂度是O(V*E)。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
int n,List[100030],vis[100030],save[100030];
vector <int> G[65];
int Find(int u)
{
for (int i=0;i<G[u].size();i++)
{
int tem=G[u][i];
if (vis[tem]==0)
{
vis[tem]=1;
if (List[tem]==-1 || Find(List[tem]))
{
List[tem]=u;
return 1;
}
}
}
return 0;
}
int solve()
{
int sum=0;
for (int i=n-1;i>=0;i--)
{
memset(vis,0,sizeof(vis));
if (Find(i)) sum++;
}
return sum;
}
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
for (int i=0;i<=60;i++)
G[i].clear();
memset(List,-1,sizeof(List));
scanf("%d",&n);
int minn=0x3f3f3f3f,maxn=-1;
for (int i=0;i<n;i++)
{
int l,r;
scanf("%d%d",&l,&r);
if (minn>l) minn=l;
if (maxn<r) maxn=r;
while (l<=r)
{
G[i].push_back(r);
r--;
}
}
int res=solve(),tem=0;
cout<<res<<endl;
for (int i=minn;i<=maxn;i++)
{
if (List[i]!=-1)
save[tem++]=List[i]+1;
}
sort(save,save+tem);
for (int i=0;i<tem;i++)
{
printf("%d",save[i]);
if (i!=tem-1) printf(" ");
else printf("\n");
}
}
}