KM匹配 hdu2853(模版

本文介绍了一种改进的Kuhn-Munkres算法用于解决特定条件下的二分图最大权匹配问题,通过调整边权值确保原有匹配尽可能不变的同时最大化整体效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门



Assignment

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


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

题意:给定一个二分图,N个点对应M个点,两两之间存在一组关系,每组关系一个权值。题目中了给定了一个匹配方案,现在要求满足这组关系中的最大的匹配权值在原方案上增长了多少?并且还要求求出在原匹配方案上改变最少多少条边能够得到这个最大匹配?

idea:增加原配边的权值,而且又不会对结果造成影响。这听起来似乎是不太可能的,但是确实有办法能够办到。首先由于顶点数最多50个,那么给所有的边都乘上55,然后再给所有的原配边都加上1,那么此时的原配边的权值相比其他边更大了,又因为我们最后求解最大权值匹配时是对结果除上55,原配边匹配再多的数量对这个结果也是于事无补,所有最后MaxValue / 55就是匹配的最大权值,而MaxValue % 55就是能够保持的最大原配边数。转自此处

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define pi acos(-1)
#define endl '\n'
#define srand() srand(time(0));
#define me(x,y) memset(x,y,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0); cin.tie(0);
#define FOR(x,n,i) for(int i=x;i<=n;i++)
#define FOr(x,n,i) for(int i=x;i<n;i++)
#define W while
#define sgn(x) ((x) < 0 ? -1 : (x) > 0)
#define bug printf("***********\n");
typedef long long LL;
const int INF=0x3f3f3f3f;
const LL LINF=0x3f3f3f3f3f3f3f3fLL;
const int dx[]={-1,0,1,0,1,-1,-1,1};
const int dy[]={0,1,0,-1,-1,1,-1,1};
const int maxn=1e3+100;
const int maxx=1e7+100;
const double EPS=1e-7;
const int MOD=10000007;
#define mod(x) ((x)%MOD);
template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}
inline int Scan()
{
    int Res=0,ch,Flag=0;
    if((ch=getchar())=='-')Flag=1;
    else if(ch>='0' && ch<='9')Res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')Res=Res*10+ch-'0';
    return Flag ? -Res : Res;
}
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.out" , "w" , stdout );
//cerr << "run time is " << clock() << endl;

int g[maxn][maxn];     //二分图表示.
int link[maxn],lx[maxn],ly[maxn];   //y的匹配关系. x,y的标杆状态.
bool visx[maxn],visy[maxn];
int nx,ny,d;   //两边的点数. 以及需要寻找的最小的d.
bool Find(int x)
{
    visx[x] = true;
    for(int i=1;i<=ny;i++)
    {
        if(visy[i]) continue;
        int tmp = lx[x] + ly[i] - g[x][i];
        if(!tmp)
        {   //tmp=0表示在当前图匹配了的边, 即看现在匹配是否合理,
            visy[i] = true;
            if(link[i] == -1 || Find(link[i]))
            {
                link[i] = x;
                return true;
            }
        }
        else d=min(d,tmp); //就是在S集合中的x,和不在T集合中的y找一个最小的d.
    }
    return false;
}

int KM()
{
    me(link,-1);
    me(ly,0); me(lx,0);
    for(int i=1;i<=nx;i++)
    {
        for(int j=1;j<=ny;j++)
        {
            if(g[i][j] > lx[i])
                lx[i] = g[i][j];
        }
    }
    for(int i =1 ; i<= nx;i++)
    {
        while(1)
        {
            me(visx,false);
            me(visy,false);
            d = INF;
            if(Find(i)) break;
            //若成功(找到了增广轨),则该点增广完成,进入下一个点的增广
            //若失败(没有找到增广轨),则需要改变一些点的标号,使得图中可行边的数量增加。
            //方法为:将所有在增广轨中(就是在增广过程中遍历到)的X方点的标号全部减去一个常数d,
            //所有在增广轨中的Y方点的标号全部加上一个常数d
            if(d == INF) return -1;    //如果可以确定左边的点都会被匹配完,则就可以不用加这条语
 //句.    如果不能就要加上这句话. (所以一般在题目中给了一定完美匹配的话,就可以不用这句话)
 //而有些题目会问你是否是完美匹配,不是的话输出-1,是的话在输出答案,所以这个时候就要加上这句话.
 //大多数题目是可以不用加的.
            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;
        }
    }
    int res = 0;
    for(int i=1;i<=ny;i++)
    {
        if(link[i] != -1)   //这些都根据题意来加.
            res += g[link[i]][i];
    }
    cout<<nx-res%55<<" ";
    return res;
}    //这道题是保证了一定有最大二分匹配的!!! 所以一些东西可以去掉.
void solve()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        me(g,0);   //找最大所以初始化为较小的值. 这样一减就会很小了.
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&g[i][j]);
                g[i][j]*=55;
            }
        int res1=0;
        nx=n;ny=m;
        for(int i=1;i<=nx;i++)
        {
            int u;
            scanf("%d",&u);
            res1+=g[i][u];
            g[i][u]++;
        }
        int res = KM();
        printf("%d\n",(res-res1)/55);
    }
}
int main()
{
    solve();
}


标题基于SpringBoot+Vue的学生交流互助平台研究AI更换标题第1章引言介绍学生交流互助平台的研究背景、意义、现状、方法与创新点。1.1研究背景与意义分析学生交流互助平台在当前教育环境下的需求及其重要性。1.2国内外研究现状综述国内外在学生交流互助平台方面的研究进展与实践应用。1.3研究方法与创新点概述本研究采用的方法论、技术路线及预期的创新成果。第2章相关理论阐述SpringBoot与Vue框架的理论基础及在学生交流互助平台中的应用。2.1SpringBoot框架概述介绍SpringBoot框架的核心思想、特点及优势。2.2Vue框架概述阐述Vue框架的基本原理、组件化开发思想及与前端的交互机制。2.3SpringBoot与Vue的整合应用探讨SpringBoot与Vue在学生交流互助平台中的整合方式及优势。第3章平台需求分析深入分析学生交流互助平台的功能需求、非功能需求及用户体验要求。3.1功能需求分析详细阐述平台的各项功能需求,如用户管理、信息交流、互助学习等。3.2非功能需求分析对平台的性能、安全性、可扩展性等非功能需求进行分析。3.3用户体验要求从用户角度出发,提出平台在易用性、美观性等方面的要求。第4章平台设计与实现具体描述学生交流互助平台的架构设计、功能实现及前后端交互细节。4.1平台架构设计给出平台的整体架构设计,包括前后端分离、微服务架构等思想的应用。4.2功能模块实现详细阐述各个功能模块的实现过程,如用户登录注册、信息发布与查看、在线交流等。4.3前后端交互细节介绍前后端数据交互的方式、接口设计及数据传输过程中的安全问题。第5章平台测试与优化对平台进行全面的测试,发现并解决潜在问题,同时进行优化以提高性能。5.1测试环境与方案介绍测试环境的搭建及所采用的测试方案,包括单元测试、集成测试等。5.2测试结果分析对测试结果进行详细分析,找出问题的根源并
内容概要:本文详细介绍了一个基于灰狼优化算法(GWO)优化的卷积双向长短期记忆神经网络(CNN-BiLSTM)融合注意力机制的多变量多步时间序列预测项目。该项目旨在解决传统时序预测方法难以捕捉非线性、复杂时序依赖关系的问题,通过融合CNN的空间特征提取、BiLSTM的时序建模能力及注意力机制的动态权重调节能力,实现对多变量多步时间序列的精准预测。项目不仅涵盖了数据预处理、模型构建与训练、性能评估,还包括了GUI界面的设计与实现。此外,文章还讨论了模型的部署、应用领域及其未来改进方向。 适合人群:具备一定编程基础,特别是对深度学习、时间序列预测及优化算法有一定了解的研发人员和数据科学家。 使用场景及目标:①用于智能电网负荷预测、金融市场多资产价格预测、环境气象多参数预报、智能制造设备状态监测与预测维护、交通流量预测与智慧交通管理、医疗健康多指标预测等领域;②提升多变量多步时间序列预测精度,优化资源调度和风险管控;③实现自动化超参数优化,降低人工调参成本,提高模型训练效率;④增强模型对复杂时序数据特征的学习能力,促进智能决策支持应用。 阅读建议:此资源不仅提供了详细的代码实现和模型架构解析,还深入探讨了模型优化和实际应用中的挑战与解决方案。因此,在学习过程中,建议结合理论与实践,逐步理解各个模块的功能和实现细节,并尝试在自己的项目中应用这些技术和方法。同时,注意数据预处理的重要性,合理设置模型参数与网络结构,控制多步预测误差传播,防范过拟合,规划计算资源与训练时间,关注模型的可解释性和透明度,以及持续更新与迭代模型,以适应数据分布的变化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值