pku2400 Supervisor, Supervisee 二分图最优匹配的全部解

题意:
给出职工对经理的评分和经理对职工的评分。求出所有的匹配方案,使得平均满意度最高

解法:
KM匹配出最优解后,根据标号遍历得所有解。注意,调整顶标以后合法匹配边仍然是l[i]+r[j]=val[i][j]

代码:

Source Code

Problem: 2400User: yzhw
Memory: 408KTime: 0MS
Language: G++Result: Accepted
  • Source Code
  • # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    using namespace std;
    # define max(a,b) ((a)>(b)?(a):(b))
    # define min(a,b) ((a)<(b)?(a):(b))
    # define N 15
    int map[N][N],match[N],ln[N],rn[N],n,c;
    bool l[N],r[N];
    bool dfs(int pos)
    {
    	//if(l[pos]) return false;
    	l[pos]=true;
    	for(int i=0;i<n;i++)
    		if(!r[i]&&ln[pos]+rn[i]==map[pos][i])
    		{
    			r[i]=true;
    			if(match[i]==-1||dfs(match[i]))
    			{
    				match[i]=pos;
    				return true;
    			}
    
    		}
    		return false;
    }
    void adjust()
    {
    	int minnum=0xfffffff;
    	for(int i=0;i<n;i++)
    		if(l[i])
    			for(int j=0;j<n;j++)
    				if(!r[j])
    					minnum=min(minnum,ln[i]+rn[j]-map[i][j]);
    	for(int i=0;i<n;i++)
    	{
    		if(l[i]) ln[i]-=minnum;
    		if(r[i]) rn[i]+=minnum;
    	}
    }
    void search(int now)
    {
    	if(now==n)
    	{
    		int ret[N];
    		for(int i=0;i<n;i++)
    			ret[match[i]]=i;
    		printf("Best Pairing %d\n",++c);
    		for(int i=0;i<n;i++)
    			printf("Supervisor %d with Employee %d\n",i+1,ret[i]+1);
    		//system("pause");
    	}
    	for(int i=0;i<n;i++)
    		if(match[i]==-1&&ln[now]+rn[i]==map[now][i])
    		{
    			match[i]=now;
    			search(now+1);
    			match[i]=-1;
    		}
    }
    int main()
    {
    	int test;
    	scanf("%d",&test);
    	for(int tt=1;tt<=test;tt++)
    	{
    		scanf("%d",&n);
    		memset(map,0,sizeof(map));
    		for(int i=0;i<n;i++)
    			for(int j=0;j<n;j++)
    			{
    				int t;
    				scanf("%d",&t);
    				map[t-1][i]-=j;
    			}
    		for(int i=0;i<n;i++)
    			for(int j=0;j<n;j++)
    			{
    				int t;
    				scanf("%d",&t);
    				map[i][t-1]-=j;
    			}
    		
    		memset(match,-1,sizeof(match));
    		memset(rn,0,sizeof(rn));
    		for(int i=0;i<n;i++)
    		{
    			int maxnum=-0xfffffff;
    			for(int j=0;j<n;j++)
    				maxnum=max(maxnum,map[i][j]);
    			ln[i]=maxnum;
    		}
    		double ans=0;
    		for(int i=0;i<n;i++)
    		{
    			memset(l,false,sizeof(l));
    			memset(r,false,sizeof(r));
    			while(!dfs(i))
    			{
    				adjust();
    				memset(l,false,sizeof(l));
    				memset(r,false,sizeof(r));
    			}
    		}
    		for(int i=0;i<n;i++)
    			ans-=map[match[i]][i];
    		printf("Data Set %d, Best average difference: %.6f\n",tt,ans/n/2.0);
    		memset(match,-1,sizeof(match));
    		c=0;
    		search(0);
    		printf("\n");
    	}
    	return 0;
    }

posted on 2011-03-08 01:39 yzhw 阅读(219) 评论(0)  编辑 收藏 引用 所属分类: graph


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2011年1月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
303112345

导航

统计

公告

统计系统

留言簿(1)

随笔分类(227)

文章分类(2)

OJ

最新随笔

搜索

积分与排名

最新评论

阅读排行榜