HDU--3729(建模*,最大匹配)
2015-06-08 15:29:15
题目:n个人参加了一次考试,每个人都有一个排名(1~n),且排名间互不相同。每个人给出一个他的排名所在的区间,(比如 [2,10] 表示他的排名在2~10之间)
但是每个人都可能撒谎,问最多可能有多少人说了真话。(n <= 60 , 区间的左右端点 <= 1e6)
思路:一个开始根本没啥思路,后来看了题解... 发现自己的思维实在太烂了...
正解是二分图最大匹配,因为每个排名值的独立的(即可以作为一个人的排名),所以对于每个人的区间 [L,R],L~R里的每个值都可以和这个人匹配,所以建边
然后其实就是求一个最大匹配了。
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <map> #include <set> #include <stack> #include <queue> #include <string> #include <iostream> #include <algorithm> using namespace std; #define getmid(l,r) ((l) + ((r) - (l)) / 2) #define MP(a,b) make_pair(a,b) #define PB(a) push_back(a) typedef long long ll; typedef pair<int,int> pii; const double eps = 1e-8; const int INF = (1 << 30) - 1; const int MAXN = 70; int T,n,num[100010],cnt; int mat[100010],used[100010]; struct node{ int x,y; }P[MAXN]; bool find(int p){ for(int i = P[p].x; i <= P[p].y; ++i){ if(used[i] == 0){ used[i] = 1; if(mat[i] == 0 || find(mat[i])){ mat[i] = p; num[p] = 1; return true; } } } return false; } int Hungary(){ int ans = 0; memset(num,0,sizeof(num)); memset(mat,0,sizeof(mat)); for(int i = n; i >= 1; --i){ memset(used,0,sizeof(used)); if(find(i)){ ++ans; } } return ans; } int main(){ scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i = 1; i <= n; ++i){ scanf("%d%d",&P[i].x,&P[i].y); } printf("%d\n",Hungary()); for(int i = 1; i <= n; ++i) if(num[i]){ printf("%d%c",i,(i == n) ? '\n' : ' '); } } return 0; }