zoukankan      html  css  js  c++  java
  • HDU 2853 && HDU 3315

    http://acm.hdu.edu.cn/showproblem.php?pid=2853

    题意:给一个n-m二分图,边权用一个n*m的矩阵表示,给出初始匹配,求二分图完美匹配相比初始匹配改变了几条边以及改变的数值

    这类题的主要思想是增加原配边的权值,但又不影响最后结果。

    步骤1:观察顶点数,每条边乘一个大于顶点数的数v

    步骤2:对于原配边,每边加1(注意步骤2可以保证km()/v的结果与原结果相同)

    步骤3:求完美匹配,答案为res,改变的边数=n-res%v(res%v表示完美匹配中有多少边属于原匹配),要求的完美匹配答案=res/v

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N=310;
    const int INF=0x3f3f3f3f;
    int nx,ny;
    int linker[N],lx[N],ly[N],slack[N];  
    int visx[N],visy[N],w[N][N];
    int DFS(int x)
    {
        visx[x]=1;
        for(int y=1;y<=ny;y++){
            if(visy[y])
                continue;
            int tmp=lx[x]+ly[y]-w[x][y];
            if(tmp==0){
                visy[y]=1;
                if(linker[y]==-1 || DFS(linker[y])){
                    linker[y]=x;
                    return 1;
                }
            }else if(slack[y]>tmp){ 
                slack[y]=tmp;
            }
        }
        return 0;
    }
    int change ;
    int KM()
    {
        int i,j;
        memset(linker,-1,sizeof(linker));
        memset(ly,0,sizeof(ly));
        for(i=1;i<=nx;i++)      
            for(j=1,lx[i]=-INF;j<=ny;j++)
                if(w[i][j]>lx[i])
                    lx[i]=w[i][j];
        for(int x=1;x<=nx;x++){
            for(i=1;i<=ny;i++)
                slack[i]=INF;
            while(1){
                memset(visx,0,sizeof(visx));
                memset(visy,0,sizeof(visy));
                if(DFS(x))  
                    break;  
                int d=INF;
                for(i=1;i<=ny;i++)
                    if(!visy[i] && d>slack[i])
                        d=slack[i];
                for(i=1;i<=nx;i++)
                    if(visx[i])
                        lx[i]-=d;
                for(i=1;i<=ny;i++) 
                    if(visy[i])
                        ly[i]+=d;
                    else
                        slack[i]-=d;
            }
        }
        int res=0;
        for(i=1;i<=ny;i++)
            if(linker[i]!=-1)
                res+=w[linker[i]][i];
        change=nx-res%200 ;
        return res/200;
    }
    int main()
    {
        while(~scanf("%d%d",&nx,&ny))
        {
            for(int i=1;i<=nx;i++)
                for(int j=1;j<=ny;j++)
                {
                    scanf("%d",&w[i][j]);
                    w[i][j]*=200 ;
                }
            int res=0 ;
            for(int i=1 ;i<=nx ;i++)
            {
                int x ;
                scanf("%d",&x) ;
                res+=w[i][x] ;
                w[i][x]++ ;
            }
            int ans=KM();
            printf("%d %d
    ",change,ans-res/200);
        }    
        return 0;
    }
    View Code

    http://acm.hdu.edu.cn/showproblem.php?pid=3315

    与2853一样思路的题目,区别是这题图没有直接给,要先算一下

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N=310;
    const int INF=0x3f3f3f3f;
    int n,nx,ny;
    int linker[N],lx[N],ly[N],slack[N];  
    int visx[N],visy[N],w[N][N];
    int DFS(int x)
    {
        visx[x]=1;
        for(int y=1;y<=ny;y++){
            if(visy[y])
                continue;
            int tmp=lx[x]+ly[y]-w[x][y];
            if(tmp==0){
                visy[y]=1;
                if(linker[y]==-1 || DFS(linker[y])){
                    linker[y]=x;
                    return 1;
                }
            }else if(slack[y]>tmp){ 
                slack[y]=tmp;
            }
        }
        return 0;
    }
    int change ;
    int KM()
    {
        int i,j;
        memset(linker,-1,sizeof(linker));
        memset(ly,0,sizeof(ly));
        for(i=1;i<=nx;i++)      
            for(j=1,lx[i]=-INF;j<=ny;j++)
                if(w[i][j]>lx[i])
                    lx[i]=w[i][j];
        for(int x=1;x<=nx;x++){
            for(i=1;i<=ny;i++)
                slack[i]=INF;
            while(1){
                memset(visx,0,sizeof(visx));
                memset(visy,0,sizeof(visy));
                if(DFS(x))  
                    break;  
                int d=INF;
                for(i=1;i<=ny;i++)
                    if(!visy[i] && d>slack[i])
                        d=slack[i];
                for(i=1;i<=nx;i++)
                    if(visx[i])
                        lx[i]-=d;
                for(i=1;i<=ny;i++) 
                    if(visy[i])
                        ly[i]+=d;
                    else
                        slack[i]-=d;
            }
        }
        int res=0;
        for(i=1;i<=ny;i++)
            if(linker[i]!=-1)
                res+=w[linker[i]][i];
        if(res<=0)return -1 ;
        change=nx-res%200 ;
        return res/200;
    }
    int V[N],H1[N],A1[N],H2[N],A2[N] ;
    int main()
    {
        while(~scanf("%d",&n),n)
        {
            nx=ny=n ;
            for(int i=1 ;i<=n ;i++)
                scanf("%d",&V[i]) ;
               for(int i=1 ;i<=n ;i++)
                   scanf("%d",&H1[i]) ;
            for(int i=1 ;i<=n ;i++)
                   scanf("%d",&H2[i]) ;
            for(int i=1 ;i<=n ;i++)
                   scanf("%d",&A1[i]) ;
            for(int i=1 ;i<=n ;i++)
                   scanf("%d",&A2[i]) ;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                {
                    int x ;
                    x=H1[i]/A2[j] ;
                    if(H1[i]%A2[j])x++ ;
                    if(x*A1[i]>=H2[j])w[i][j]=V[i]*200 ;
                    else w[i][j]=(-V[i]*200) ;
                }
            for(int i=1 ;i<=n ;i++)
                w[i][i]++ ;
            int ans=KM();
            if(ans==-1)puts("Oh, I lose my dear seaco!") ;
            else printf("%d %.3lf%%
    ",ans,(nx-change)*100.0/n);
        }    
        return 0;
    }
    View Code
  • 相关阅读:
    Codevs 2296 仪仗队 2008年省队选拔赛山东
    Codevs 1535 封锁阳光大学
    Codevs 1069 关押罪犯 2010年NOIP全国联赛提高组
    Codevs 1218 疫情控制 2012年NOIP全国联赛提高组
    Codevs 1684 垃圾陷阱
    洛谷 P1108 低价购买
    Vijos P1325桐桐的糖果计划
    Codevs 3289 花匠 2013年NOIP全国联赛提高组
    Codevs 2611 观光旅游(floyed最小环)
    C语言基础之彩色版C语言(内含linux)
  • 原文地址:https://www.cnblogs.com/xiaohongmao/p/3891583.html
Copyright © 2011-2022 走看看