• poj 3565 uva 1411 Ants KM算法求最小权


      由于涉及到实数,一定,一定不能直接等于,一定,一定加一个误差<0.00001,坑死了……

      有两种事物,不难想到用二分图。这里涉及到一个有趣的问题,这个二分图的完美匹配的最小权值和就是答案。为啥呢?因为如果有四个点,a,b,c,d Abcd交叉,acbd不交叉,那么acbd的长度和一定小于abcd的长度和,可以画一个图很容易就证出来。所以,如果所有的边都不交叉,又因为有解,那么最小的权值和就是解了。附图一枚,自己画的,比较简陋,凑活着看吧……

      KM算法求最佳完美匹配最小权值和,可以直接把所有的权值转成负值,在求最大权值和,但是这种方法我觉得有些不对劲,但是不知道在哪里= =,上网一查,才发现这种方法只能用于xy数量相同的时候,正统做法应该是用一个很大的数减去每个权值,再求最大权值和。PS:我用的是取反的方法……

     

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #define N 110
    struct sss
    {
        int x,y;
    }white[N],black[N];
    int n,vx[N],vy[N],fa[N];
    double w[N][N],px[N],py[N],str[N];
    double dis(int i,int j)
    {
        return sqrt((double)(black[i].x-white[j].x)*(black[i].x-white[j].x)+(double)(black[i].y-white[j].y)*(black[i].y-white[j].y));
    }
    int find(int now)
    {
        int i,j,k;
        if (now==0)
          return 1;
        vx[now]=1;
        for (i=1;i<=n;i++)
        {
          if (!vy[i]&&fabs(px[now]+py[i]-w[now][i])<0.00001)
          {
              vy[i]=1;
              if (fa[i]==0||find(fa[i]))
              {
                  fa[i]=now;
                  return 1;
              }
          }
          else
            if (str[i]>px[now]+py[i]-w[now][i])
              str[i]=px[now]+py[i]-w[now][i];
        }
        return 0;
    }
    void KM()
    {
        int i,j,k,x,y,z;
        double na;
        memset(fa,0,sizeof(fa));
        for (i=1;i<=n;i++)
        {
            memset(str,0x7f,sizeof(str));
            while (1)
            {
                memset(vx,0,sizeof(vx));
                memset(vy,0,sizeof(vy));
                if (find(i))
                  break;
                na=0x7f;
                for (j=1;j<=n;j++)
                  if (!vy[j]&&na>str[j])
                    na=str[j];
                for (j=1;j<=n;j++)
                {
                    if (vx[j])
                      px[j]-=na;
                    if (vy[j])
                      py[j]+=na;
                    else
                      str[j]-=na;
                }
            }
        }
    }
    int main()
    {
        int i,j,k,x,y,z;
        z=0;
        while(scanf("%d",&n)!=EOF)
        {
            if (z)
              printf("
    ");
            else
              z=1;
            for (i=1;i<=n;i++)
              px[i]=-100000;
            memset(py,0,sizeof(py));
            for (i=1;i<=n;i++)
              scanf("%d%d",&white[i].x,&white[i].y);
            for (i=1;i<=n;i++)
              scanf("%d%d",&black[i].x,&black[i].y);
            for (i=1;i<=n;i++)
              for (j=1;j<=n;j++) 
              {
                  w[i][j]=-dis(i,j);
                  if (px[i]<w[i][j])
                    px[i]=w[i][j];
              }
            KM();
            for (i=1;i<=n;i++)
              printf("%d
    ",fa[i]);
        }
    }

     

  • 相关阅读:
    CRC校验码原理、实例、手动计算
    RAID级别
    ffmbc——广播电视以及专业用途量身定制的FFmpeg
    Linux查看物理CPU个数、核数、逻辑CPU个数
    Linux服务器高并发实践经历
    Linux解压命令大全
    针对文件系统和网络性能的测试
    代码覆盖工具(gcov、lcov)的使用
    MYSQL的卸载
    Moosefs源代码分析
  • 原文地址:https://www.cnblogs.com/handsomeJian/p/3575536.html
Copyright © 2020-2023  润新知