标签:key sni aced through 最小 else and fwrite sam
【POJ 2400】 Supervisor, Supervisee(KM求最小权匹配)
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 2538 | Accepted: 719 |
Description
Input
Output
Sample Input
2 7 1 2 3 4 5 6 7 2 1 3 4 5 6 7 3 1 2 4 5 6 7 4 1 2 3 5 6 7 5 1 2 3 4 6 7 6 1 2 3 4 5 7 7 1 2 3 4 5 6 1 2 3 4 5 6 7 2 1 3 4 5 6 7 3 1 2 4 5 6 7 4 1 2 3 5 6 7 5 1 2 3 4 6 7 6 1 2 3 4 5 7 7 1 2 3 4 5 6 2 1 2 2 1 1 2 1 2
Sample Output
Data Set 1, Best average difference: 0.000000 Best Pairing 1 Supervisor 1 with Employee 1 Supervisor 2 with Employee 2 Supervisor 3 with Employee 3 Supervisor 4 with Employee 4 Supervisor 5 with Employee 5 Supervisor 6 with Employee 6 Supervisor 7 with Employee 7 Data Set 2, Best average difference: 0.250000 Best Pairing 1 Supervisor 1 with Employee 1 Supervisor 2 with Employee 2
Source
题目大意就是n个上司与n名员工。每一个上司相应有想要搭配的员工。相同每一个员工有渴望搭配的上司。
输入第一行为N 之后n行为1~n号上司的期望 从左到右从最好到最差
相同之后n行是1~n号员工
匹配到最渴望的人值为0,否则从左到右一次加1
要求问平均期望的最小值,也就是最小值/2n
最小值用KM最小权匹配计算就可以,因为还要求输出解,有多解则输出多解。所以还要搜一下……
事实上数据非常少。找最小权匹配也用搜的也能够。
。
。
代码例如以下:
#include <iostream> #include <cmath> #include <vector> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <list> #include <algorithm> #include <map> #include <set> #define LL long long #define fread() freopen("in.in","r",stdin) #define fwrite() freopen("out.out","w",stdout) using namespace std; const int INF = 0x3f3f3f3f; const int msz = 10000; const double eps = 1e-8; int mp[23][33]; int lx[33],ly[33],link[33],slack[33],next[33]; bool visx[33],visy[33],vis[33]; int n,ans,cnt; bool cal(int x) { visx[x] = 1; for(int y = 0; y < n; ++y) { if(visy[y]) continue; int t = lx[x]+ly[y]-mp[x][y]; if(t == 0) { visy[y] = 1; if(link[y] == -1 || cal(link[y])) { link[y] = x; return 1; } } else slack[y] = min(slack[y],t); } return 0; } int KM() { memset(link,-1,sizeof(link)); for(int i = 0; i < n; ++i) { memset(slack,INF,sizeof(slack)); while(1) { memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); if(cal(i)) break; int d = INF; for(int i = 0; i < n; ++i) if(!visy[i]) d = min(d,slack[i]); for(int i = 0; i < n; ++i) if(visx[i]) lx[i] -= d; for(int i = 0; i < n; ++i) if(visy[i]) ly[i] += d; else slack[i] -= d; } } ans = 0; for(int i = 0; i < n; ++i) if(link[i] != -1) ans += mp[link[i]][i]; return -ans; } void dfs(int id,int hs) { if(hs < ans) return; if(id == n) { if(hs == ans) { printf("Best Pairing %d\n",++cnt); for(int i = 0; i < n; ++i) { printf("Supervisor %d with Employee %d\n",i+1,next[i]+1); } } return; } for(int i = 0; i < n; ++i) { if(vis[i]) continue; vis[i] = 1; next[id] = i; dfs(id+1,hs+mp[id][i]); vis[i] = 0; } } int main() { int t,x; scanf("%d",&t); for(int z = 1; z <= t; ++z) { scanf("%d",&n); memset(ly,0,sizeof(ly)); for(int i = 0; i < n; ++i) for(int j = 0; j < n; ++j) { scanf("%d",&x); mp[x-1][i] = -j; } for(int i = 0; i < n; ++i) for(int j = 0; j < n; ++j) { scanf("%d",&x); mp[i][x-1] -= j; if(j == 0) lx[i] = mp[i][x-1]; else lx[i] = max(lx[i],mp[i][x-1]); } printf("Data Set %d, Best average difference: %.6f\n",z,KM()*0.5/n); cnt = 0; memset(vis,0,sizeof(vis)); dfs(0,0); puts(""); } return 0; }
【POJ 2400】 Supervisor, Supervisee(KM求最小权匹配)
标签:key sni aced through 最小 else and fwrite sam
原文地址:http://www.cnblogs.com/jhcelue/p/7255362.html