1. 程式人生 > >洛谷 P1559 運動員最佳匹配問題

洛谷 P1559 運動員最佳匹配問題

style for printf ++ har head time http pan

題目描述

羽毛球隊有男女運動員各n人。給定2 個n×n矩陣P和Q。P[i][j]是男運動員i和女運動員j配對組成混合雙打的男運動員競賽優勢;Q[i][j]是女運動員i和男運動員j配合的女運動員競賽優勢。由於技術配合和心理狀態等各種因素影響,P[i][j]不一定等於Q[j][i]。男運動員i和女運動員j配對組成混合雙打的男女雙方競賽優勢為P[i][j]*Q[j][i]。設計一個算法,計算男女運動員最佳配對法,使各組男女雙方競賽優勢的總和達到最大。

輸入輸出格式

輸入格式:

第一行有1 個正整數n (1≤n≤20)。接下來的2n行,每行n個數。前n行是p,後n行是q。

輸出格式:

將計算出的男女雙方競賽優勢的總和的最大值輸出。

輸入輸出樣例

輸入樣例#1:
3
10 2 3
2 3 4
3 4 5
2 2 2
3 5 3
4 5 1
輸出樣例#1:
52
二分圖費用流 不會km。。 n<=20 也可以dfs 屠龍寶刀點擊就送 費用流做法
#include <cstdio>
#include <queue>
#define N 40000
#define FWQ 0xefefefef
using namespace
std; struct Edge { int next,to,flow,cost; Edge (int next=0,int to=0,int flow=0,int cost=0) :next(next),to(to),flow(flow),cost(cost) {} }edge[N<<1]; int dis[N],head[N],n,p[25][25],q[25][25],fa[N],cnt=1; inline void ins(int u,int v,int w,int l) { edge[++cnt]=Edge(head[u],v,w,l); head[u]
=cnt; } bool vis[N]; bool spfa(int s,int t) { for(int i=s;i<=t;++i) dis[i]=FWQ,vis[i]=0; dis[s]=0; queue<int>q; q.push(s); for(int now;!q.empty();) { now=q.front();q.pop();vis[now]=0; for(int i=head[now];i;i=edge[i].next) { int v=edge[i].to; if(dis[v]<dis[now]+edge[i].cost&&edge[i].flow) { dis[v]=dis[now]+edge[i].cost; fa[v]=i; if(!vis[v]) { vis[v]=1; q.push(v); } } } } return dis[t]!=FWQ; } int dinic(int S,int T) { int ret=0; for(;spfa(S,T);) { for(int i=T;i!=S&&i;i=edge[fa[i]^1].to) { edge[fa[i]].flow--; edge[fa[i]^1].flow++; } ret+=dis[T]; } return ret; } int main(int argc,char *argv[]) { scanf("%d",&n); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) scanf("%d",&p[i][j]); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) scanf("%d",&q[i][j]); int S=0,T=n*2+1; for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) ins(i,j+n,1,p[i][j]*q[j][i]),ins(j+n,i,0,-p[i][j]*q[j][i]); for(int i=1;i<=n;++i) ins(S,i,1,0),ins(i,S,0,0); for(int i=n+1;i<=n+n;++i) ins(i,T,1,0),ins(T,i,0,0); printf("%d\n",dinic(S,T)); return 0;

洛谷 P1559 運動員最佳匹配問題