• HDU 2853 & 剩余系+KM模板


    题意:

      给你一张二分图,给一个原匹配,求原匹配改动最少的边数使其边权和最大。

    SOL:

      我觉得我的智商还是去搞搞文化课吧。。这种题给我独立做我大概只能在暴力优化上下功夫。。

      这题的处理方法让我想到了剩余系。。貌似就是它。。

      我们将每条边的边权扩大n+1倍——是不是有点雾,同时将原匹配边的边权再加1.

      非常玄学!这样做有什么道理呢?它保证了最优匹配在这样更改后仍是最优的!我们假设次优解比最优解只小1,在乘上n+1后差距被放大到n+1,即使次优解全由原匹配边组成,加上n仍小于最优解,那么我们就一定能求出最优解。同时我们注意到每一条边的边权均为n+1的倍数,而原匹配边的边权为n+1的倍数加1,那么我们就能很方便地求出当前解中有多少原匹配边。

      如果原图有多个最优解,那么我们能肯定拥有原匹配边最多的解在乘上n+1后边权最大——毕竟人家加了1嘛。

      很巧妙的剩余系转化与运用啊。。数学渣确实已经没救了。

    /*==========================================================================
    # Last modified: 2016-02-19 13:00
    # Filename: hdu2853.cpp
    # Description: 
    ==========================================================================*/
    #define me AcrossTheSky 
    #include <cstdio> 
    #include <cmath> 
    #include <ctime> 
    #include <string> 
    #include <cstring> 
    #include <cstdlib> 
    #include <iostream> 
    #include <algorithm> 
      
    #include <set> 
    #include <map> 
    #include <stack> 
    #include <queue> 
    #include <vector> 
    #define lowbit(x) (x)&(-x) 
    #define INF 1070000000 
    #define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++) 
    #define FORP(i,a,b) for(int i=(a);i<=(b);i++) 
    #define FORM(i,a,b) for(int i=(a);i>=(b);i--) 
    #define ls(a,b) (((a)+(b)) << 1) 
    #define rs(a,b) (((a)+(b)) >> 1) 
    #define maxn 100
    using namespace std; 
    typedef long long ll; 
    typedef unsigned long long ull; 
    /*==================split line==================*/ 
    int n,m;
    int slack[maxn],lx[maxn],ly[maxn],w[maxn][maxn],link[maxn];
    bool S[maxn],T[maxn];
    int Ans;
    bool match(int i){
    	S[i]=true;
    	FORP(j,1,m)
    	if (!T[j]){
    		int tmp=lx[i]+ly[j]-w[i][j];
    		if (tmp==0){
    			T[j]=true;
    			if (!link[j] || match(link[j])){
    				link[j]=i;
    				return true;
    			}
    		}
    		else slack[j]=min(slack[j],tmp);
    	}
    	return false;
    }
    void updata(){
    	int a=INF;
    	FORP(i,1,m) if (!T[i]) a=min(a,slack[i]);
    	FORP(i,1,n) if (S[i]) lx[i]-=a;
    	FORP(i,1,m) 
    		if (T[i]) ly[i]+=a;
    			else slack[i]-=a;
    }
    void KM(){
    	memset(lx,0,sizeof(lx));
    	memset(link,0,sizeof(link));
    	memset(ly,0,sizeof(ly));
    	FORP(i,1,n)
    		FORP(j,1,m) lx[i]=max(lx[i],w[i][j]);
    	FORP(i,1,n){
    		memset(slack,0x7f,sizeof(slack));
    		while (true){
    			memset(S,false,sizeof(S));
    			memset(T,false,sizeof(T));
    			if (match(i)) break;
    			else updata();
    		}
    	}
    	int ans=0;
    	FORP(i,1,m) if (link[i]) ans+=w[link[i]][i];
    	printf("%d %d
    ",n-ans%(n+1),ans/(n+1)-Ans/(n+1));
    }
    int main(){ 
    	freopen("a.in","r",stdin);
    	while (scanf("%d%d",&n,&m)!=EOF){
    		Ans=0;
    		FORP(i,1,n) 
    			FORP(j,1,m) {
    				int x;
    				scanf("%d",&x);
    				w[i][j]=x*(n+1);
    			}
    		FORP(i,1,n) {int x; scanf("%d",&x); Ans+=w[i][x]; w[i][x]++;}
    		KM();
    	}
    }
    
    Sometimes it s the very people who no one imagines anything of. who do the things that no one can imagine.
  • 相关阅读:
    Linux chattr 文件保护
    ArcGIS案例学习笔记-批处理擦除挖空挖除相减
    ArcGIS案例学习笔记-手动编辑擦除挖空挖除相减
    GIS案例学习笔记-CAD数据分层导入现有模板实例教程
    GIS案例学习笔记-ArcGIS整图大图出图实例教程
    Arcgis map export or print Error: Cannot map metafile into memory. Not enough memory
    [图解tensorflow源码] 入门准备工作附常用的矩阵计算工具[转]
    GIS案例学习笔记-明暗等高线提取地理模型构建
    地理处理模型、案例、教程、培训低价发送
    GIS工具-shp浏览器
  • 原文地址:https://www.cnblogs.com/YCuangWhen/p/5200828.html
Copyright © 2020-2023  润新知