zoukankan      html  css  js  c++  java
  • ZOJ-3933 Team Formation (二分图最佳完美匹配)

    题目大意:n个人,分为两个阵营。现在要组成由若干支队伍,每支队伍由两个人组成并且这两个人必须来自不同的阵营。同时,每个人都有m个厌恶的对象,并且厌恶是相互的。相互厌恶的人不能组成一支队伍。问最多能组成多少支队伍,并在在队伍数最多的前提下求最多的女生数以及输出方案。

    题目分析:很显然是个二分图。从阵营1的每个元素向阵营0的每个元素连一条有向边(互相厌恶的不连),这就得到一张二分图。给每条边一个权值,边两端的女生越多,权值越大。只需要求最大完美匹配即可。

    ps:比赛的时候连边只连了一半儿,导致一直wa。。。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<cstring>
    # include<vector>
    # include<queue>
    # include<list>
    # include<set>
    # include<map>
    # include<string>
    # include<cmath>
    # include<cstdlib>
    # include<algorithm>
    using namespace std;
    # define LL long long
    
    const int N=1005;
    const int INF=1000000000;
    const LL oo=0x7fffffffffffffff;
    const double eps=1e-10;
    
    int n;
    int mp[N/2+5][N/2+5];
    int slack[N/2+5];
    int link[N/2+5];
    int lx[N/2+5];
    int ly[N/2+5];
    int s[N/2+5],t[N/2+5];
    int vis[N/2+5][N/2+5];
    string p,q;
    
    bool match(int x)
    {
    	s[x]=1;
    	for(int y=0;y<n;++y){
    		if(t[y]) continue;
    		int temp=lx[x]+ly[y]-mp[x][y];
    		if(temp==0){
    			t[y]=1;
    			if(link[y]==-1||match(link[y])){
    				link[y]=x;
    				return true;
    			}
    		}else if(slack[y]>temp)
    			slack[y]=temp;
    	}
    	return false;
    }
    
    void update()
    {
    	int d=INF;
    	for(int i=0;i<n;++i) if(!t[i])
    		d=min(d,slack[i]);
    	for(int i=0;i<n;++i) if(s[i]) lx[i]-=d;
    	for(int i=0;i<n;++i){
    		if(t[i]) ly[i]+=d;
    		else slack[i]-=d;
    	}
    }
    
    void KM()
    {
    	memset(link,-1,sizeof(link));
    	memset(ly,0,sizeof(ly));
    	for(int i=0;i<n;++i){
    		lx[i]=-1;
    		for(int j=0;j<n;++j)
    			lx[i]=max(lx[i],mp[i][j]);
    	}
    	for(int i=0;i<n;++i){
    		fill(slack,slack+n,INF);
    		while(true){
    			memset(s,0,sizeof(s));
    			memset(t,0,sizeof(t));
    			if(match(i))
    				break;
    			update();
    		}
    	}
    }
    
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%d",&n);
    		cin>>p>>q;
    		memset(mp,0,sizeof(mp));
    		memset(vis,0,sizeof(vis));
    		for(int i=0;i<n;++i){
    			int k;
    			scanf("%d",&k);
    			while(k--){
    				int a;
    				scanf("%d",&a);
    				vis[i][a-1]=vis[a-1][i]=1;
    			}
    			for(int j=0;j<n;++j){
    				if(i==j||p[i]==p[j]||vis[i][j]||vis[j][i]) continue;
    				int gg=1;      ///这里如果为gg=0会wa
    				if(q[i]=='0') ++gg;
    				if(q[j]=='0') ++gg;
    				if(p[i]=='1'&&p[j]=='0') mp[i][j]=gg;
    				else if(p[i]=='0'&&p[j]=='1') mp[j][i]=gg;
    			}
    		}
    		KM();
    		int ansa=0,ansb=0;
    		for(int i=0;i<n;++i) if(link[i]!=-1&&mp[link[i]][i]){
    			++ansa;
    			if(q[link[i]]=='0') ++ansb;
    			if(q[i]=='0') ++ansb;
    		}
    		printf("%d %d
    ",ansa,ansb);
    		for(int i=0;i<n;++i) if(link[i]!=-1&&mp[link[i]][i])
    			printf("%d %d
    ",link[i]+1,i+1);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    简单所以不要忽视,关于 和 程序员应了解的实际应用
    即使用ADO.NET,也要轻量级动态生成更新SQL,比Ormlite性能更高
    即使用ADO.NET,也要轻量级实体映射,比Dapper和Ormlite均快
    如何在前端实现语义缩放(第一步)
    react教程 — 性能优化
    react教程 — 组件
    react教程 — redux
    create-react-app 创建项目 及 配置
    CSS 预处理器
    react 和 vue 对比
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/5449293.html
Copyright © 2011-2022 走看看