zoukankan      html  css  js  c++  java
  • 带权二分图——KM算法hdu2255 poj3565

    进阶指南的板子好像有点问题。。交到hdu上会T

    需要了解的一些概念:

      交错树,顶标,修改量

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    #define INF 99999999
    #define maxn 305
     
    int lx[maxn],ly[maxn];//顶标
    int Match[maxn];//记录匹配值
    int visx[maxn],visy[maxn];
    int w[maxn][maxn];//权值
    int slack[maxn];//slack为修改量
    int ans,n;
     
    bool findPath(int x){
        visx[x]=1;
        for(int y=1; y<=n; y++){
            if(visy[y])continue;
            if(w[x][y]==lx[x]+ly[y]){//如果是相等子图则加入交错树中 
                visy[y]=1;
                if(!Match[y]||findPath(Match[y])){//增广后不用再考虑交错树 
                    Match[y]=x;
                    return true;
                }
            }
            else//不能加入交错树中的点,用来更新修改量 
            slack[y]=min(slack[y],lx[x]+ly[y]-w[x][y]);
        }
        return false;
    }
    void km(){
        memset(Match,0,sizeof(Match));
        memset(lx,0,sizeof(lx));
        memset(ly,0,sizeof(ly));
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                    lx[i]=max(lx[i],w[i][j]);
                    
        for(int x=1; x<=n; x++){
            for(int i=1;i<=n;i++)slack[i]=INF;//初始化修改量 
            while(1){
                memset(visx,0,sizeof(visx));
                memset(visy,0,sizeof(visy));
                if(findPath(x))break;//直到x找到一个匹配点时退出循环 
                //如果没找到匹配点(增广失败),那么找最小修改量, 
                int tmp=INF;
                for(int i=1;i<=n;i++){
                    if(!visy[i]){
                        if(tmp>slack[i])
                        tmp=slack[i];
                    }
                }
                //更新交错树中的顶标 
                for(int i=1; i<=n; i++){
                    if(visx[i]) lx[i]-=tmp;
                    if(visy[i]) ly[i]+=tmp;else slack[i]-=tmp;
                }
            }
        }
    }
    int main(){
        while(scanf("%d",&n)!=EOF){
            ans=0;
            for(int i=1; i<=n; i++)
                for(int j=1; j<=n; j++)
                    scanf("%d",&w[i][j]);
            km();
            for(int i=1; i<=n; i++)
                ans+=w[Match[i]][i];
            printf("%d
    ",ans);
        }
        return 0;
    }
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int MAXN = 110;
    const double INF = 0xffffffffffff;
    const double eps = 1e-6;
     
    struct Node
    {
        double x,y;
    }Dot1[MAXN],Dot2[MAXN];
     
    double Dist(Node a,Node b)
    {
        return -sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
     
    int N,NX,NY;
    double Map[MAXN][MAXN];
    int link[MAXN];
    double lx[MAXN],ly[MAXN],slack[MAXN];
    int visx[MAXN],visy[MAXN];
     
    int FindPath(int u)
    {
        visx[u] = 1;
        for(int i = 1; i <= NY; ++i)
        {
            if(visy[i])
                continue;
            double temp = lx[u] + ly[i] - Map[u][i];
            if(fabs(temp) <= eps)
            {
                visy[i] = 1;
                if(link[i] == -1 || FindPath(link[i]))
                {
                    link[i] = u;
                    return 1;
                }
            }
            else
            {
                if(slack[i] > temp)
                    slack[i] = temp;
            }
        }
        return 0;
    }
     
    void KM()
    {
        memset(lx,0,sizeof(lx));
        memset(ly,0,sizeof(ly));
        memset(link,-1,sizeof(link));
        for(int i = 1; i <= NX; ++i) 
        {
        lx[i] = -INF;
            for(int j = 1; j <= NY; ++j)
                if(Map[i][j] > lx[i])
                    lx[i] = Map[i][j];
        }
     
        for(int i = 1; i <= NX; ++i)
        {
            for(int j = 1; j <= NY; ++j)
                slack[j] = INF;
            while(1)
            {
                memset(visx,0,sizeof(visx));
                memset(visy,0,sizeof(visy));
                if(FindPath(i))
                    break;
                double d = INF;
                for(int j = 1; j <= NY; ++j)
                    if(!visy[j] && d > slack[j])
                        d = slack[j];
                for(int j = 1; j <= NX; ++j)
                    if(visx[j])
                        lx[j] -= d;
                for(int j = 1; j <= NY; ++j)
                {
                    if(visy[j])
                        ly[j] += d;
                    else
                        slack[j] -= d;
                }
            }
        }
    }
     
    int main()
    {
        int N;
        while(~scanf("%d",&N))
        {
            memset(Map,0,sizeof(Map));
            for(int i = 1; i <= N; ++i)
                scanf("%lf%lf",&Dot1[i].x,&Dot1[i].y);
            for(int i = 1; i <= N; ++i)
                scanf("%lf%lf",&Dot2[i].x,&Dot2[i].y);
     
            for(int i = 1; i <= N; ++i)
                for(int j = 1; j <= N; ++j)
                    Map[i][j] = Dist(Dot1[i],Dot2[j]);
     
            NX = NY = N;
            KM();
            for(int i = 1; i <= N; ++i)
            {
                for(int j = 1; j <= N; ++j)
                {
                    if(link[j] == i)
                    {
                        printf("%d
    ",j);
                        break;
                    }
                }
            }
        }
     
        return 0;
    }
  • 相关阅读:
    汇编笔记(1) 寄存器
    阿里云RDS数据库备份文件恢复到本地数据库
    Java调用HTTPS接口的证书配置
    SQL面试题之行转列
    WebsiteCrawler
    supervisor
    简单学习github代码托管
    [egret+pomelo]实时对战游戏杂记(5)
    [egret+pomelo]实时游戏杂记(4)
    [egret+pomelo]实时游戏杂记(3)
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10889478.html
Copyright © 2011-2022 走看看