zoukankan      html  css  js  c++  java
  • Assignment (HDU 2853 最大权匹配KM)


    Assignment

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 1068    Accepted Submission(s): 551


    Problem Description
    Last year a terrible earthquake attacked Sichuan province. About 300,000 PLA soldiers attended the rescue, also ALPCs. Our mission is to solve difficulty problems to optimization the assignment of troops. The assignment is measure by efficiency, which is an integer, and the larger the better.
    We have N companies of troops and M missions, M>=N. One company can get only one mission. One mission can be assigned to only one company. If company i takes mission j, we can get efficiency Eij. 
    We have a assignment plan already, and now we want to change some companies’ missions to make the total efficiency larger. And also we want to change as less companies as possible.
     

    Input
    For each test case, the first line contains two numbers N and M. N lines follow. Each contains M integers, representing Eij. The next line contains N integers. The first one represents the mission number that company 1 takes, and so on.
    1<=N<=M<=50, 1<Eij<=10000.
    Your program should process to the end of file.
     

    Output
    For each the case print two integers X and Y. X represents the number of companies whose mission had been changed. Y represents the maximum total efficiency can be increased after changing.
     

    Sample Input
    3 3 2 1 3 3 2 4 1 26 2 2 1 3 2 3 1 2 3 1 2 3 1 2
     

    Sample Output
    2 26 1 2
     

    Source
     

    Recommend
    gaojie   |   We have carefully selected several similar problems for you:  2855 2854 2856 2857 2858 


    题意:n个公司m个任务。每一个公司仅仅接受一个任务。每一个任务仅仅被一个公司接受,每一个公司i接受任务j的做事效率为g[i][j],如今已经分配好了。问如何改变任务分配能够让效率最大,求出要修改的公司数目和添加的效率。

    思路:与hdu3315相似,hdu 3315若点数为N,则把每条边的权值扩大x倍(x>N),若是原有匹配。则再把权值加1。最后KM算法求出ans,则最大权值之和=ans/x。没有被修改的=ans%x。

    代码:


    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <string>
    #include <map>
    #include <stack>
    #include <vector>
    #include <set>
    #include <queue>
    #pragma comment (linker,"/STACK:102400000,102400000")
    #define maxn 1005
    #define MAXN 2005
    #define mod 1000000009
    #define INF 0x3f3f3f3f
    #define pi acos(-1.0)
    #define eps 1e-6
    #define lson rt<<1,l,mid
    #define rson rt<<1|1,mid+1,r
    #define FRE(i,a,b)  for(i = a; i <= b; i++)
    #define FREE(i,a,b) for(i = a; i >= b; i--)
    #define FRL(i,a,b)  for(i = a; i < b; i++)
    #define FRLL(i,a,b) for(i = a; i > b; i--)
    #define mem(t, v)   memset ((t) , v, sizeof(t))
    #define sf(n)       scanf("%d", &n)
    #define sff(a,b)    scanf("%d %d", &a, &b)
    #define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
    #define pf          printf
    #define DBG         pf("Hi
    ")
    typedef long long ll;
    using namespace std;
    
    /*
    KM算法 O(nx*nx*ny)
    求最大权匹配(最佳匹配)
    若求最小权匹配,可将权值取相反数,结果取相反数
    点的标号从0開始
    */
    
    const int N=110;
    int nx,ny;      //两边的点数
    int g[N][N];    //二分图描写叙述,g赋初值为-INF
    int linker[N],lx[N],ly[N];  //y 中各点匹配状态。x,y中的点的标号
    int slack[N];
    bool visx[N],visy[N];
    bool flag;
    
    bool DFS(int x)
    {
        visx[x]=true;
        for (int y=0;y<ny;y++)
        {
            if (visy[y]) continue;
            int tmp=lx[x]+ly[y]-g[x][y];
            if (tmp==0)
            {
                visy[y]=true;
                if (linker[y]==-1||DFS(linker[y]))
                {
                    linker[y]=x;
                    return true;
                }
            }
            else if (slack[y]>tmp)
                slack[y]=tmp;
        }
        return false;
    }
    
    int KM()
    {
        flag=true;
        memset(linker,-1,sizeof(linker));
        memset(ly,0,sizeof(ly));
        for (int i=0;i<nx;i++) //赋初值。lx置为最大值
        {
            lx[i]=-INF;
            for (int j=0;j<ny;j++)
            {
                if (g[i][j]>lx[i])
                    lx[i]=g[i][j];
            }
        }
        for (int x=0;x<nx;x++)
        {
            for (int i=0;i<ny;i++)
                slack[i]=INF;
            while (true)
            {
                memset(visx,false,sizeof(visx));
                memset(visy,false,sizeof(visy));
                if (DFS(x)) break;
                int d=INF;
                for (int i=0;i<ny;i++)
                    if (!visy[i]&&d>slack[i])
                        d=slack[i];
                for (int i=0;i<nx;i++)
                    if (visx[i])
                        lx[i]-=d;
                for (int i=0;i<ny;i++)
                {
                    if (visy[i])
                        ly[i]+=d;
                    else
                        slack[i]-=d;
                }
            }
        }
        int res=0;
        for (int i=0;i<ny;i++)
        {
            if (linker[i]==-1||g[linker[i]][i]<=-INF) //有的点不能匹配的话return-1
            {
                flag=false;
                continue;
            }
            res+=g[linker[i]][i];
        }
        return res;
    }
    //记得nx和ny初始化!

    !!!

    !!

    。! int n,m; int main() { #ifndef ONLINE_JUDGE freopen("C:/Users/asus1/Desktop/IN.txt","r",stdin); #endif int i,j,x; while (~sff(n,m)) { nx=n; ny=m; int sum=0; for (i=0;i<n;i++) for (j=0;j<m;j++) { sf(x); g[i][j]=x*100; } for (i=0;i<n;i++) { sf(x);x--; sum+=g[i][x]; g[i][x]++; } int ans=KM(); printf("%d %d ",n-ans%100,ans/100-sum/100); } return 0; } /* 3 3 2 1 3 3 2 4 1 26 2 2 1 3 2 3 1 2 3 1 2 3 1 2 */



  • 相关阅读:
    Saltstack的部署及其详解
    SSH免密远程登陆及详解
    LVS-负载均衡集群部署
    nginx的平滑升级
    MFS分布式文件系统管理
    cacti监控部署与配置
    Nagios部署与配置
    zabbix分布式监控的部署与win被控端
    Fail2防止sshd暴力破解
    C# 发邮件
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/5372338.html
Copyright © 2011-2022 走看看