此题是我AC的HDU的201道题目。泪流满面啊!
字典序最大(最小)真是个烦人的东西。
学生i与其对应的分数区间的每个点连一条边。字典序最大,编号最大的学生开始匹配。
HK无法AC啊,试了很久。我不会说,能过样例。
最后用了DFS版的匈牙利算法过了。人们说这个代码简洁。不过我一般都用HK,时间复杂度低。今天发现了这个,还是有收获的。下次什么字典序,就用匈牙利。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<algorithm> 6 using namespace std; 7 const int N=65,M=110050,INF=0x3f3f3f3f; 8 bool bmask[M]; 9 int cx[N],cy[M]; 10 int nx,ans; 11 vector<int> bmap[N]; 12 int findpath(int u) 13 { 14 int i,j; 15 for(j=0;j<bmap[u].size();j++) 16 { 17 i=bmap[u][j]; 18 if(!bmask[i]) 19 { 20 bmask[i]=1; 21 if(cy[i]==-1||findpath(cy[i])) 22 { 23 cy[i]=u; cx[u]=i; 24 return 1; 25 } 26 } 27 } 28 return 0; 29 } 30 void maxmatch() 31 { 32 int i ,j; 33 ans=0; 34 memset(cx,-1,sizeof(cx)); 35 memset(cy,-1,sizeof(cy)); 36 for(i=nx;i>=1;i--) 37 { 38 if(cx[i]==-1) 39 { 40 memset(bmask,0,sizeof(bmask)); 41 ans+=findpath(i); 42 } 43 } 44 } 45 int main() 46 { 47 //freopen("test.txt","r",stdin); 48 int cas,i,j,k,n,a,b; 49 scanf("%d",&cas); 50 while(cas--) 51 { 52 scanf("%d",&n); 53 for(i=1;i<=n;i++) 54 { 55 bmap[i].clear(); 56 scanf("%d%d",&a,&b); 57 for(k=a;k<=b;k++) 58 bmap[i].push_back(k); 59 } 60 nx=n; 61 maxmatch(); 62 printf("%d ",ans); 63 for(i=1;i<=nx;i++) 64 { 65 if(cx[i]!=-1) 66 { 67 printf("%d",i); 68 ans--; 69 if(ans) printf(" "); 70 else printf(" "); 71 } 72 } 73 } 74 return 0; 75 }