http://poj.org/problem?id=3686
拆点+KM算法
题目大意:
n个玩具在m台机器上完成所需时间个不同
一台机器只有完成一个玩具的的制作才能继续完成其它的
问你n给玩具完成制作最小平均时间
思路转自
http://blog.sina.com.cn/s/blog_6af663940100mw9t.html
此题构图很巧妙。设n个订单的执行时间分别为t1,t2…tn,则n个订单的总的执行时间是
t1*n+t2*(n-1)+t3*(n-2)+…+tn-1*2+tn。将每个机器j拆成n个点,第k个点表示倒数第k个订单在此机器上完成,连边权值为:tmp[i][j]*k。这样就转换成了求二分图最小权匹配的问题了。KM算法,把权值设为负值求最大权匹配
求的是最小平均时间 把时间转换为负的 就可以求最大匹配了
我个人直接用三维数组储存的,这样原来的右组就由一维变成了二维
其它的都一样了
代码及其注释:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int MAX=0x7ffffff; const int N=51; int paytime[N][N][N]; //拆点后花费时间, int a[N]; //左组顶标 int b[N][N]; //右组顶标 bool lv[N]; //左组是否在交叉树内 bool rv[N][N]; //右组是否在交叉树内 int n,m; int f[N][N]; //右组指向 bool dfs( int x) //匈牙利算法找匹配 { lv[x]= true ; for ( int i=1;i<=m;++i) { for ( int j=1;j<=n;++j) { if (!rv[i][j]&&a[x]+b[i][j]==paytime[x][i][j]) { rv[i][j]= true ; if (f[i][j]==-1||dfs(f[i][j])) { f[i][j]=x; return true ; } } } } return false ; } int KM() { memset (b,0, sizeof (b)); for ( int i=1;i<=n;++i) { a[i]=-MAX; for ( int j=1;j<=m;++j) { for ( int l=1;l<=n;++l) { a[i]=max(a[i],paytime[i][j][l]); //左组顶标初始最大 } } } memset (f,-1, sizeof (f)); for ( int w=1;w<=n;++w) { while (1) { memset (lv, false , sizeof (lv)); memset (rv, false , sizeof (rv)); if (dfs(w)) //匹配的话直接退出循环找下一个 否则减d继续找 break ; int d=MAX; for ( int i=1;i<=n;++i) { if (lv[i]) { for ( int j=1;j<=m;++j) { for ( int l=1;l<=n;++l) { if (!rv[j][l]) { d=min(d,a[i]+b[j][l]-paytime[i][j][l]); //找最小变化量 } } } } } for ( int i=1;i<=n;++i) { if (lv[i]) a[i]-=d; } for ( int j=1;j<=m;++j) { for ( int l=1;l<=n;++l) { if (rv[j][l]) b[j][l]+=d; } } } } int sum=0; for ( int j=1;j<=m;++j) { for ( int l=1;l<=n;++l) { if (f[j][l]!=-1) sum-=paytime[f[j][l]][j][l]; //最优匹配总值 } } return sum; } int main() { int T; scanf ( "%d" ,&T); while (T--) { scanf ( "%d %d" ,&n,&m); int k; for ( int i=1;i<=n;++i) { for ( int j=1;j<=m;++j) { scanf ( "%d" ,&k); for ( int l=1;l<=n;++l) { paytime[i][j][l]=-(k*l); //拆点 } } } printf ( "%.6f\n" ,1.0*(KM())/n); } return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步