• POJ3686 The Windy's 最小权匹配


      题目链接:http://poj.org/problem?id=3686

      这个题目容易想到拆点,开始我是直接拆点在求的,考虑到直接建图复杂度有点高,然后就在找增广路的同时再加点,因为并不是每个点都会达到50个,这样实际复杂度会好很多。敲完之后,样例过了,然后直接叫,WA!后来看了discuss顿然醒悟,找增光路的时候,之前的状态改变了,那么后面的状态也会改变,那么那样求下去就不一定是最优解!所有要保证所有的匹配之间是互补影响的!假设某个工作坊要处理K个命令,时间分别是t1,t2......tk,那么总共的时间就是k*t1+(k-1)*t2+......+tk。发现没有,如果k表示的是倒数第k个命令,那么总时间变为了:t1+2*t2+......+k*tk。所以我们拆点后再建图的时候,边权值w[i][j]*k,(1<=k<=50),那么直接求最小权匹配就行了。那么我们看下时间复杂度,匹配n个点O(n),每个点至多找n次增广路O(n),邻接矩阵的匈牙利O(n^2),总共就是O(50*50*2500*2500),这是理论的时间复杂度,但实际上远远没有这么可怕,因为很难达到最坏情况,而且顶标的维护使得匈牙利算法效率大大的高,所以一般就算O(n^4)的KM算法也够用了。我的代码POJ跑了47ms,这也出乎了我的意料,总感觉POJ的题目数据很弱啊!!!

     1 //STATUS:G++_AC_47MS_1344KB
     2 #include<stdio.h>
     3 #include<stdlib.h>
     4 #include<string.h>
     5 #include<math.h>
     6 #include<iostream>
     7 #include<string>
     8 #include<algorithm>
     9 #include<vector>
    10 #include<queue>
    11 #include<stack>
    12 using namespace std;
    13 #define LL long long
    14 #define Max(a,b) ((a)>(b)?(a):(b))
    15 #define Min(a,b) ((a)<(b)?(a):(b))
    16 #define mem(a,b) memset(a,b,sizeof(a))
    17 #define lson l,mid,rt<<1
    18 #define rson mid+1,r,rt<<1|1
    19 const int MAX=55,INF=0x3f3f3f3f;
    20 
    21 int w[MAX][MAX*MAX],S[MAX],T[MAX*MAX],lx[MAX],ly[MAX*MAX],y[MAX*MAX];
    22 int Test,n,m,slack;
    23 
    24 int dfs(int u)
    25 {
    26     int v,t;
    27     S[u]=1;
    28     for(v=0;v<m;v++){
    29         t=w[u][v]-lx[u]-ly[v];
    30         if(!t){
    31             if(!T[v]){
    32                 T[v]=1;
    33                 if(y[v]==-1 || dfs(y[v])){
    34                     y[v]=u;
    35                     return 1;
    36                 }
    37             }
    38         }
    39         else if(t<slack)slack=t;
    40     }
    41     return 0;
    42 }
    43 
    44 double KM()
    45 {
    46     int i,j;
    47     double s;
    48     mem(ly,0);
    49     mem(y,-1);
    50     for(i=0;i<n;i++){
    51         lx[i]=INF;
    52         for(j=0;j<m;j++)
    53             if(w[i][j]<lx[i])lx[i]=w[i][j];
    54     }
    55     for(i=0;i<n;i++){
    56         while(1){
    57             slack=INF;
    58             mem(S,0);mem(T,0);
    59             if(dfs(i))break;
    60             for(j=0;j<n;j++)if(S[j])lx[j]+=slack;
    61             for(j=0;j<m;j++)if(T[j])ly[j]-=slack;
    62         }
    63     }
    64     for(i=s=0;i<m;i++)
    65         if(y[i]!=-1)s+=w[y[i]][i];
    66     return s;
    67 }
    68 
    69 int main()
    70 {
    71  //   freopen("in.txt","r",stdin);
    72     int i,j,k,t;
    73     double ans;
    74     scanf("%d",&Test);
    75     while(Test--)
    76     {
    77         scanf("%d%d",&n,&m);
    78         for(i=0;i<n;i++)
    79             for(j=0;j<m;j++)
    80                 scanf("%d",&w[i][j]);
    81         for(i=0,t=m;i<t;i++)
    82             for(j=2;j<=50;j++,m++)
    83                 for(k=0;k<n;k++)
    84                     w[k][m]=w[k][i]*j;
    85         ans=KM();
    86 
    87         printf("%.6f\n",ans/n);
    88     }
    89     return 0;
    90 }
  • 相关阅读:
    Javascript高级篇-Function对象
    Object类、instanceof
    [一]Head First设计模式之【策略模式】(鸭子设计的优化历程)
    匿名内部类
    设计模式之单例模式
    长江商业评论读书笔记
    [转]Freemarker数据类型转换
    面向对象编程——概论(一)
    IP地址处理模块IPy
    系统性能模块psutil
  • 原文地址:https://www.cnblogs.com/zhsl/p/2786349.html
Copyright © 2020-2023  润新知