HDU-3729 I'm Telling the Truth

一个点集是学生,一个点集是排名。然后通过学生的排名范围连线,求此二分图的最大匹配。

本题还要求是最大字典序输出,那么由贪心可得,你让标号从大到小找增广边就行了。

#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <fstream>
#include <iostream>

#define rep(i, l, r) for(int i=l; i<=r; i++)
#define down(i, l, r) for(int i=l; i>=r; i--)
#define N 69
#define M 100009

using namespace std;
int read()
{
	int x=0, f=1; char ch=getchar();
	while (ch<'0' || ch>'9') { if (ch=='-') f=-1; ch=getchar(); }
	while (ch>='0' && ch<='9') { x=x*10+ch-'0'; ch=getchar(); }
	return x*f;
}

int n, l[N], r[N], k[M], b[M], ans, ansk[N], s;

bool Find(int x)
{
	rep(i, l[x], r[x]) if (b[i]!=s) 
	{
		b[i]=s; if (!k[i] || Find(k[i])) { k[i]=x; return true; }
	}
	return false;
}

int main()
{
	int t=read(); while (t--)
	{
		n=read();
		rep(i, 1, n) l[i]=read(), r[i]=read();
		rep(i, 1, M-1) k[i]=b[i]=0; 
		rep(i, 1, n) ansk[i]=0; ans=0;
		down(i, n, 1) if (Find(s=i)) ans++, ansk[i]=1;
		printf("%d\n", ans);
		rep(i, 1, n) if (ansk[i]) { if (--ans) printf("%d ", i); else printf("%d\n", i); }
	}
	return 0;
}

  

转载于:https://www.cnblogs.com/NanoApe/p/4345570.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值