想看更多的解题报告: http://blog.csdn.net/wangjian8006/article/details/7870410
转载请注明出处:http://blog.csdn.net/wangjian8006
题目大意:国王有n个儿子,现在这n个儿子要在n个女孩里选择自己喜欢的,有的儿子可能喜欢多个,最后国王的向导给出他一个匹配
匹配有n个数,代表某个儿子和哪个女孩可以结婚
已知这些条件,要你找出每个儿子可以和哪些女孩结婚
解题思路:因为给出是一个二分图,很容易会往二分匹配那方面去想,我第一个想法是对于每个儿子,去进行匈牙利匹配。匹配到一个人就删除这
条边,接着匹配,直到不能匹配再恢复到原图,对下一个儿子进行这样的操作。
直到n个儿子都匹配完了,就可以得出一个顺序
看了讨论版,居然用强联通分量去建图,
建图:首先哪个儿子喜欢哪个女的,就用那个儿子的编号指向那个女的的编号
完备匹配就用建相应的反向边
这样分析,如果某个男的可以和女的结婚,那么他们肯定是在一个连通分量里面的,当然,如果他们想结婚的前提是男的必须喜欢女的
/* 内存太大,建议用邻接表写,这题调的太久,懒得写了 听说用putchar和getchar+G++提交可以进入几百秒内 Memory 63412K Time 4641MS */ #include <iostream> #include <vector> #include <stack> using namespace std; #define MAXV 4020 #define min(a,b) (a>b?b:a) vector <int>ans; stack <int>stap; int map[MAXV][MAXV]; int dfn[MAXV],low[MAXV],belong[MAXV]; int count,n,cnt; bool instack[MAXV]; void init(){ count=cnt=0; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(instack,0,sizeof(instack)); } void tarjan(int x){ int i; dfn[x]=low[x]=++cnt; stap.push(x); instack[x]=true; for(i=1;i<=n<<1;i++){ if(!map[x][i]) continue; if(!dfn[i]){ tarjan(i); low[x]=min(low[i],low[x]); }else if(instack[i]) low[x]=min(dfn[i],low[x]); } if(low[x]==dfn[x]){ count++; while(1){ int tmp=stap.top(); stap.pop(); belong[tmp]=count; instack[tmp]=false; if(tmp==x) break; } } } void work(){ init(); for(int i=1;i<=2*n;i++) if(!dfn[i]) tarjan(i); } int main(){ int i,j,num; scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%d",&num); while(num--){ scanf("%d",&j); map[i][j+n]=1; } } for(i=1;i<=n;i++){ scanf("%d",&j); map[j+n][i]=1; } work(); for(i=1;i<=n;i++){ ans.clear(); for(j=n+1;j<=n<<1;j++){ if(map[i][j] && belong[i]==belong[j]){ ans.push_back(j-n); } } printf("%d",ans.size()); for(j=0;j<ans.size();j++) printf(" %d",ans[j]); printf("\n"); } return 0; }
====================================================================
纪念下超时的代码....
/* Time Limit Exceeded */ #include <iostream> using namespace std; #define MAXV 2001 int n; bool map[MAXV][MAXV],use[MAXV]; int ans[MAXV][MAXV]; int record[MAXV]; int link[MAXV]; int dfs(int x){ int i,j; for(i=1;i<=n;i++){ if(!use[i] && map[x][i]){ use[i]=1; j=link[i]; link[i]=x; if(j==-1 || dfs(j)) return true; link[i]=j; } } return false; } bool hungary(){ int i; memset(link,-1,sizeof(link)); for(i=1;i<=n;i++){ memset(use,0,sizeof(use)); if(!dfs(i)) return false; } return true; } int cmp(const void *a,const void *b){ return *(int *)a-*(int *)b; } int main(){ int i,j,num; while(~scanf("%d",&n)){ memset(map,0,sizeof(map)); for(i=1;i<=n;i++){ scanf("%d",&num); while(num--){ scanf("%d",&j); map[i][j]=1; } } memset(ans,0,sizeof(ans)); for(i=1;i<=n;i++){ scanf("%d",&j); num=0; map[i][j]=0; ans[i][++ans[i][0]]=j; record[num++]=j; while(hungary()){ ans[i][++ans[i][0]]=link[i]; record[num++]=link[i]; map[i][link[i]]=0; } for(j=0;j<num;j++) map[i][record[j]]=1; //恢复 } for(i=1;i<=n;i++){ printf("%d",ans[i][0]); qsort(ans[i]+1,ans[i][0],sizeof(ans[0][0]),cmp); for(j=1;j<=ans[i][0];j++) printf(" %d",ans[i][j]); printf("\n"); } } return 0; }