题目描述
英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1名是外籍飞行员。在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合。如何选择配对飞行的飞行员才能使一次派出最多的飞机。对于给定的外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。
对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。
输入输出格式
输入格式:
第 1 行有 2 个正整数 m 和 n。n 是皇家空军的飞行员总数(n<100);m 是外籍飞行员数(m<=n)。外籍飞行员编号为 1~m;英国飞行员编号为 m+1~n。
接下来每行有 2 个正整数 i 和 j,表示外籍飞行员 i 可以和英国飞行员 j 配合。最后以 2个-1 结束。
输出格式:
第 1 行是最佳飞行员配对方案一次能派出的最多的飞机数 M。接下来 M 行是最佳飞行员配对方案。每行有 2个正整数 i 和 j,表示在最佳飞行员配对方案中,飞行员 i 和飞行员 j 配对。如果所求的最佳飞行员配对方案不存在,则输出‘No Solution!’。
输入输出样例
输入样例#1: 复制
5 10 1 7 1 8 2 6 2 9 2 10 3 7 3 8 4 7 4 8 5 10 -1 -1
输出样例#1: 复制
View Code
View Code
4 1 7 2 9 3 8 5 10
注意匈牙利算法vis的运用 !!!vis[]存的是右图的匹配情况
只用连左图到右图的即可
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// #define inf 0x3f3f3f3 const int N=1000000; const int M=1000000; int head[M],pos; struct Edge { int nex,to; }edge[M]; void add(int a,int b) { edge[++pos].nex=head[a]; head[a]=pos; edge[pos].to=b; } int n,m; int vis[N],used[N]; int flag=0; bool dfs(int x) { for(int i=head[x];i;i=edge[i].nex) { int v=edge[i].to; if(!used[v]) { used[v]=1; if(!vis[v]||dfs(vis[v])) { vis[v]=x;return 1; } } } return 0; } int find1() { int ans=0; CLR(vis,0); rep(i,1,n) { CLR(used,0); if(dfs(i))ans++; } return ans; } int main() { RII(n,m); int a,b; while(RII(a,b)) { if(a==-1&&b==-1) break; add(b,a); } int cnt=find1(); if(!cnt) printf("No Solution"); else { cout<<cnt<<endl; rep(i,n+1,m) { if(vis[i]) printf("%d %d ",vis[i],i); } } return 0; }
网络流
注意初始化!!!!
只要看反向边是否为0即可输出结果
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// #define inf 0x3f3f3f3f const int N=10000+5; const int M=200000+5; int head[M],pos; struct Edge { int to,nex=-1,v; }edge[M]; void init() { pos=-1; CLR(head,-1); } void add(int a,int b,int c) { edge[++pos].nex=head[a]; head[a]=pos; edge[pos].to=b; edge[pos].v=c; edge[++pos].nex=head[b]; head[b]=pos; edge[pos].to=a; edge[pos].v=0; } int deth[N]; int bfs(int s,int t) { CLR(deth,0); queue<int>q; deth[s]=1; q.push(s); while(!q.empty()) { int u=q.front();q.pop(); for(int i=head[u];i!=-1;i=edge[i].nex) { int v=edge[i].to; if(edge[i].v>0&&deth[v]==0) { deth[v]=deth[u]+1; q.push(v); } } } return deth[t]; } int dfs(int s,int t,int dis) { if(s==t)return dis; for(int i=head[s];i!=-1;i=edge[i].nex) { int v=edge[i].to; if(deth[v]==deth[s]+1&&edge[i].v!=0) { int di=dfs(v,t,min(dis,edge[i].v)); if(di>0) { edge[i].v-=di; edge[i^1].v+=di; return di; } } } return 0; } int dinic(int s,int t) { int ans=0; while(bfs(s,t)) while(int di=dfs(s,t,inf)) ans+=di; return ans; } int main() { int n,m; RII(n,m); int s=m+1,e=m+2; int a,b; init(); while(RII(a,b)) { if(a==-1&&b==-1)break; add(a,b,1); } rep(i,1,n) add(s,i,1); rep(i,n+1,m) add(i,e,1); int cnt=dinic(s,e); if(cnt==0) printf("No Solution! "); else { cout<<cnt<<endl; } for(int i=0;i<=pos;i+=2) { int a=edge[i].to;int b=edge[i^1].to; if(a!=s&&b!=s) if(a!=e&&b!=e) if(edge[i^1].v!=0) { printf("%d %d ",b,a); } } return 0; }