zoukankan      html  css  js  c++  java
  • [网络流24题]飞行员配对方案问题

    Description

    英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1名是外籍飞行员。在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合。如何选择配对飞行的飞行员才能使一次派出最多的飞机。对于给定的外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。

    对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。

    Code

    二分图匹配问题,可用最大流或匈牙利算法

    //最大流sap
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define Inf 0x7fffffff
    #define N 110
    using namespace std;
    
    struct info{
    	int nex,to,f;
    }e[N*N];
    int n,m,Ans,dis[N],head[N],cnt[N],S,T,tot;
    
    void Link(int u,int v){
    	e[++tot].nex=head[u];
    	e[tot].f=1;e[tot].to=v;head[u]=tot;
    	e[++tot].nex=head[v];
    	e[tot].f=0;e[tot].to=u;head[v]=tot;
    }
    
    int sap(int u,int delta){
    	int sum=0,mins=n;
    	if(u==T) return delta;
    	
    	for(int i=head[u];i;i=e[i].nex){
    		int v=e[i].to;
    		if(e[i].f>0&&dis[u]==dis[v]+1){
    			int save=sap(v,min(delta-sum,e[i].f));
    			sum+=save;
    			e[i].f-=save;
    			e[i^1].f+=save;
    			if(dis[S]>=n||sum==delta) return sum;
    		}
    		if(e[i].f>0) mins=min(mins,dis[v]);
    	}
    	if(sum==0){
    		if(!(--cnt[dis[u]])) dis[S]=n;
    		else ++cnt[dis[u]=mins+1];
    	}
    	return sum;
    }
    
    int main(){
    	scanf("%d%d",&m,&n);
    	S=0,T=n+1;tot=-1;
    	int u,v,tmp;
    	while(~scanf("%d%d",&u,&v)){
    		if(u+v==-2) break;
    		Link(u,v);
    	}
    	for (int i=1;i<=m;++i) Link(S,i);
        for (int i=m+1;i<=n;++i) Link(i,T);
        n+=2;cnt[0]=n;
    	while(dis[S]<n) Ans+=sap(S,Inf);
    	printf("%d
    ",Ans);
    	for(int i=0;i<=tot;i+=2)//输出方案
    		if(e[i].fr!=S&&e[i].to!=S&&e[i].fr!=T&&e[i].to!=T&&e[i^1].f!=0)
    			printf("%d %d
    ",e[i].fr,e[i].to);
    	return 0;
    }
    

    匈牙利,

    #include <cstdio>
    #include <cstring>
    #define N 110
    using namespace std;
    
    int n,m,ans=0,node[N];
    bool line[N][N],used[N];
    
    bool find(int k)
    {
        for(int i=1;i<=m;++i)
        {
            if(line[k][i]&&!used[i])
            {
                used[i]=1;
                if(!node[i]||find(node[i]))
                {
                    node[i]=k;
                    return 1;
                }
            }
        }
        return 0;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        int a,b;
        while(1)
        {
            scanf("%d%d",&a,&b);
            if(a==-1&&b==-1) break;
            line[a][b]=1;
        }
        for(int i=1;i<=n;++i)
        {
            memset(used,0,sizeof(used));
            if(find(i)) ++ans;
        }
        if(!ans)
        {
            printf("No Solution!
    ");
            return 0;
        }
        printf("%d
    ", ans);
        for(int i=1;i<=m;++i)
            if(node[i])
        	{
            	printf("%d %d
    ", node[i],i);
        	}
        return 0;
    }
    
  • 相关阅读:
    ASP.NET MVC5写.php路由匹配时的问题 ASP.NET MVC 4 在 .NET 4.0 与.NET 4.5 的專案範本差異
    asp.net mvc上传头像加剪裁功能介绍
    图片延迟加载实现
    c#中多线程访问winform控件的若干问题
    C# WinForm实现控件拖动实例介绍
    C# 实现对窗体(Form)换肤
    C#读写txt文件的两种方法介绍
    C#实现JSON序列化与反序列化介绍
    高效的VS调试技巧
    SQL 添加字段和默认值脚本
  • 原文地址:https://www.cnblogs.com/void-f/p/8287052.html
Copyright © 2011-2022 走看看