• hihocoder 1393 : 网络流三·二分图多重匹配


    标签: hihocoder 网络流 二分图


    描述

    学校的秋季运动会即将开始,为了决定参赛人员,各个班又开始忙碌起来。
    小Hi和小Ho作为班上的班干部,统计分配比赛选手的重任也自然交到了他们手上。
    已知小Hi和小Ho所在的班级一共有N名学生(包含小Hi和小Ho),编号依次为1..N。
    运动会一共有M项不同的比赛,编号为1..M。第i项比赛每个班需要派出m[i]名选手参加。
    根据小Hi和小Ho的统计,编号为i的学生表示最多同时参加a[i]项比赛,并且给出他所擅长的b[i]项比赛的编号。
    小Hi和小Ho希望将每个学生都安排到他所擅长的比赛项目,以增加夺冠的可能性。同时又要考虑满足每项比赛对人数的要求,当然给一个学生安排的比赛项目也不能超过他愿意参加的比赛项目数量。
    根据统计的结果,小Hi和小Ho想知道能否有一个合适的安排,同时满足这些条件。
    提示:二分图多重匹配

    输入

    第1行:1个整数T,表示一共有T(2≤T≤5)组数据,每组数据按如下格式给出:
    第1行:2个正整数N,M。1≤N≤100,1≤M≤100。
    第2行:M个整数,第i个数表示第i个项目需要的选手数量m[i]。1≤m[i]≤N。
    第3..N+2行:若干整数,第i+2行表示编号为i的学生的信息。先是a[i],b[i],接下来b[i]个整数,表示其所擅长的b[i]个项目。1≤a[i]≤M

    输出

    第1..T行:第i行表示第i组数据能否满足要求,若能够输出"Yes",否则输出"No"。

    样例输入

    2
    4 3
    1 2 2
    1 2 1 2
    2 2 1 3
    1 1 2
    1 2 2 3
    4 3
    2 2 2
    1 2 1 2
    2 2 1 3
    1 1 2
    1 2 2 3
    

    样例输出

    Yes
    No
    

    分析

    首先建立假想的源点和汇点。
    对于第(i)个人来说,他只能参加(a_i)个项目,所以将源点 (s)(i) 的容量设置为(a_i)
    对于第(i)个项目来说,只能有(m_i)个人参加,所以将(n+i)向汇点的容量设置为(m_i)
    如果第(i)个人擅长(j)项目,那么把(i)(j)的容量设置为(1).
    然后跑最大流即可。
    (PS:为什么又没有卡Ford-Fulkerson的数据?)

    代码

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <cstdio>
    #include <map>
    #include <set>
    using namespace std;
    typedef long long ll;
    const ll MOd=1e9+7;
    const int inf=0x3f3f3f3f;
    const int maxn=150;
    struct Edge
    {
    	int v,nxt,c,f;
    }e[100050];
    int h[maxn*2],tot;
    void addEdge(int x,int y,int w){
    	e[++tot]=(Edge){y,h[x],w,0};
    	h[x]=tot;
    }
    int n,m,s,t;
    bool vis[maxn*2];
    ll dfs(int x,ll flow){
    	if(vis[x]||flow==0) return 0;
    	vis[x]=true;
    	if(x==t) return flow;
    	ll ans=0;
    	for (int i = h[x]; i ; i=e[i].nxt)
    	{
    		ll t=min(flow,(ll)e[i].c-e[i].f);
    		if(t>0 && (ans=dfs(e[i].v,t))){
    			e[i].f+=ans;
    			return ans;
    		}
    		t=min(flow,(ll)e[i^1].f);
    		if(t>0 && (ans=dfs(e[i].v,t))){
    			e[i^1].f-=ans;
    			return ans;
    		}
    	}
    	return 0;
    }
    int main(int argc, char const *argv[])
    {
    	int T;
    	scanf("%d", &T);
    	while(T--){
    		scanf("%d%d", &n,&m);
    		s=0,t=n+m+1;
    		for (int i = 0; i <= t; ++i)
    		{
    			h[i]=0;
    		}
    		tot=1;
    		ll M=0;
    		for (int i = n+1; i <= n+m; ++i)
    		{
    			int w;
    			scanf("%d", &w);
    			addEdge(i,t,w);
    			addEdge(t,i,0);
    			M+=w;
    		}
    		for (int i = 1; i <= n; ++i)
    		{
    			int a,b;
    			scanf("%d%d", &a,&b);
    			addEdge(s,i,a);
    			addEdge(i,s,0);
    			while(b--){
    				int x;
    				scanf("%d", &x);
    				addEdge(i,x+n,1);
    				addEdge(x+n,i,0);
    			}
    		}
    		ll sum=0,flow=0;
    		memset(vis,false,sizeof vis);
    		while(flow=dfs(s,inf)){
    			sum+=flow;
    			memset(vis,false,sizeof vis);
    		}
    		bool ans=true;
    		if(sum!=M) ans=false;
    		printf(ans?"Yes
    ":"No
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    Windows7下面手把手教你安装Django
    windows系统下Python环境的搭建
    PHP、Java、Python、C、C++ 这几种编程语言都各有什么特点或优点
    结构化程序设计 ?
    编译性语言、解释性语言和脚本语言
    在linux中关闭防火墙
    Linux下Apache服务的查看和启动
    AWS中,如果使用了ELB,出现outofservice
    亚马逊的PuTTY连接AWS出现network error connection refused,终极解决方案。
    9.Node.js 包管理器npm
  • 原文地址:https://www.cnblogs.com/sciorz/p/9037841.html
Copyright © 2020-2023  润新知