题意:有n个主管和n个职工,每个主管对职工有不同的喜好程度,职工也是,最喜欢的为0(每行第一个),后面的依次+1,求最优搭配,输出方案
思路:跑一下最小费最大流,然后用dfs搜索最小费的方案,数据不是很大
PS:输入数据有误,应该先是每个职工的喜好,再是主管的喜好
#include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; typedef long long ll; const int maxn = 35; struct edge { int to,cf,w,rev; }; int d[maxn],fa[maxn],inq[maxn],pr[maxn]; vector v[maxn]; int ans,n,vis[maxn],num,line[maxn][maxn]; void init(int x) { for(int i = 0; i <= x; i++) v[i].clear(); } void add(int from,int to,int cap,int cost) { v[from].push_back((edge){to,cap,cost,v[to].size()}); v[to].push_back((edge){from,0,-cost,v[from].size()-1}); } int mincost(int s,int t) { queue q; while(!q.empty()) q.pop(); int c,f; c = f = 0; while(1) { memset(fa,-1,sizeof fa); memset(d,0x3f,sizeof d); d[s] = 0; memset(inq,0,sizeof inq); q.push(s); while(!q.empty()) { int x = q.front();q.pop(); inq[x] = 0; for(int i = 0; i < v[x].size(); i++) { edge e = v[x][i]; int y = e.to; if(e.cf && d[y] > d[x] + e.w) { d[y] = d[x] + e.w; fa[y] = x; pr[y] = i; if(!inq[y]) { inq[y] = 1; q.push(y); } } } } if(d[t] == 0x3f3f3f3f) break; int gen = 0x3f3f3f3f; for(int a = t; a != s; a = fa[a]) gen = min(gen,v[fa[a]][pr[a]].cf); for(int a = t; a != s; a = fa[a]) { edge &e = v[fa[a]][pr[a]]; e.cf -= gen; v[a][e.rev].cf += gen; } f += gen; c += gen * d[t]; } return c;//f 最大流,c最小费用 } void dfs(int x,int sum) { if(sum > ans) return; if(x > n) { if(sum < ans) return; printf("Best Pairing %d\n",num++); for(int i = 1; i <= n; i++) printf("Supervisor %d with Employee %d\n",i,vis[i]-n); return; } for(int i = n+1; i <= 2*n; i++) { if(!vis[i]) { vis[i] = 1; vis[x] = i; dfs(x+1,sum+line[x][i]); vis[i] = 0; } } } int main(void) { int T,i,j,k,kase = 1; scanf("%d",&T); while(T--) { scanf("%d",&n); init(2*n+1); memset(line,0,sizeof line); for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++) { scanf("%d",&k); line[k][i+n] += j-1; } } for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++) { scanf("%d",&k); line[i][k+n] += j-1; } } for(i = 1; i <= n; i++) { for(j = n+1; j <= 2*n; j++) add(i,j,1,line[i][j]); } for(i = 1; i <= n; i++) add(0,i,1,0); for(i = n+1; i <= 2*n; i++) add(i,2*n+1,1,0); ans = mincost(0,2*n+1); printf("Data Set %d, Best average difference: %f\n",kase++,ans/(2.0*n)); num = 1; memset(vis,0,sizeof vis); dfs(1,0); putchar('\n'); } return 0; }