zoukankan      html  css  js  c++  java
  • 【题解】2021牛客暑期多校第三场 C.Minimum grid

    2021牛客暑期多校第三场Minimum grid

    题意

    给定一个(n imes n)的方阵,有(m)个位置需要填数,且每一行的数的最大值为(b_i),每一列数的最大值为(c_i),求方阵中所有数和的最小值。

    (1le nle 2 imes 10^3,1le mle 8 imes 10^5,1le b_i,c_ile k,1le kle 10^6),且所有(b_i,c_i)中相同的值最多出现(500)次。

    题解

    填入的数只需要是(b_i,c_i)(0)。从大到小一次考虑每一种权值(v),将(b_i=v)的行和(c_i=v)得列提出来构成一个子阵,对行和列建点,对可以填数的位置的行列之间连边,则这种权值对答案的贡献为(最小边覆盖*权值=(行数+列数-最大匹配)*权值)。由于各个权值之间互不干扰,故不需要对每个权值分别建图,直接建一个图后跑二分图匹配即可。

    #include <bits/stdc++.h>
    #define pb(x) emplace_back(x)
    using namespace std;
    using ll=long long ;
    const int N=2005;
    int match[N],vis[N];
    vector<int> g[N];
    int n,m,k,a[N],b[N];
    ll ans=0;
    int dfs(int u){
    	for(auto v:g[u])if(!vis[v]){
    		vis[v]=1;
    		if(!match[v]||dfs(match[v])){
    			match[v]=u;return 1;
    		}
    	}
    	return 0;
    }
    void f1(){
    	scanf("%d%d%d",&n,&m,&k);
    	for(int i=1;i<=n;i++){
    		cin>>a[i];ans+=a[i];
    	}
    	for(int i=1;i<=n;i++){
    		cin>>b[i];ans+=b[i];
    	}
    	while(m--){
    		int x,y;cin>>x>>y;
    		if(a[x]==b[y]){g[x].pb(y);}
    	}
    	for(int i=1;i<=n;i++){
    		memset(vis,0,sizeof(vis));
    		dfs(i);
    	}
    	for(int i=1;i<=n;i++){
    		if(match[i])ans-=b[i];
    	}
    	cout<<ans;
    } 
    int main(){
    	f1();
    	return 0;
    }
    
  • 相关阅读:
    VS2005快捷键(转)
    codeSmish使用《转》
    WinForm TextBox数据绑定
    NetTiers抛出"Unable To Load NetTiersServiceSection“的异常
    DELPHi第三方控件使用方法(摘录)
    遠程連接操作
    不同服务器数据库之间的数据操作
    delphi 关闭 MDI 子窗体
    VSS使用手册(转)
    delphi 快捷键
  • 原文地址:https://www.cnblogs.com/bobh/p/15061462.html
Copyright © 2011-2022 走看看