链接
https://ac.nowcoder.com/acm/contest/11254/C
题意
$n*n$ 的网格中,给出每行每列的最大权值,有 $m$ 个位置可以分配权值,求这 $m$ 个位置满足每行每列的最大权值的最小权值和。
思路
行列最大权值的上限为 $1e6$,考虑从大到小枚举权值,记当前枚举到 $x$:
对于最大权值为 $x$ 的行列建立二分图,易发现填 $x$ 的格子数为当前二分图点数 $-$ 最大匹配数。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| #include <bits/stdc++.h> #define SZ(x) (int)(x).size() #define ALL(x) (x).begin(),(x).end() #define PB push_back #define EB emplace_back #define MP make_pair #define FI first #define SE second using namespace std; typedef double DB; typedef long double LD; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; typedef vector<int> VI; typedef vector<PII> VPII;
const int N=1e6+5; VI mx1[N],mx2[N],a,b; int match[505]; bool w[2005][2005],st[505]; bool dfs(int u) { for(int v=0;v<SZ(b);v++) if(w[a[u]][b[v]]&&!st[v]) { st[v]=true; if(match[v]==-1||dfs(match[v])) { match[v]=u; return true; } } return false; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n,m,k;cin>>n>>m>>k; for(int i=1;i<=n;i++) { int x;cin>>x; mx1[x].PB(i); } for(int i=1;i<=n;i++) { int x;cin>>x; mx2[x].PB(i); } for(int i=1;i<=m;i++) { int x,y;cin>>x>>y; w[x][y]=true; } int res=0; for(int i=k;i;i--) { a.clear(); b.clear(); for(auto x:mx1[i]) a.PB(x); for(auto x:mx2[i]) b.PB(x); for(int i=0;i<SZ(b);i++) match[i]=-1; int cnt=SZ(a)+SZ(b); for(int i=0;i<SZ(a);i++) { for(int j=0;j<SZ(b);j++) st[j]=false; if(dfs(i)) --cnt; } res+=cnt*i; } cout<<res<<'\n'; return 0; }
|