Minimum grid
生活随笔
收集整理的這篇文章主要介紹了
Minimum grid
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Minimum grid
題意:
一個n * n的矩陣,有m個位置需要填數(shù),填的數(shù)的范圍是0<=k<=1e6,需要滿足第i行的最大值是b,第j列的最大值是ci,求一個滿足條件的最小代價
n<=2e3,m<=8e5,k<=1e6
題解:
如果直接填,我們需要滿足每行每列的最大值,第i行最大值是a,第j行最大值是b,我們需要第i行單獨有一個格子權(quán)值是a,第j行單獨有一個格子的權(quán)值是b,這樣代價是a+b,但是如果第i行和第j行的最大值都是a,我們可以直接在(i,j)這個格子上放a,這樣即滿足條件且代價降低(用一個a干了兩個a的事)
如果現(xiàn)在第1行,第2行,第3行,第3列,第4列的最大值都是a,那么才怎么分配呢?我們把行放一側(cè),列放一側(cè),這不就是二分圖嗎,跑最大匹配即可,最大匹配就省下的a的數(shù)量。也就是(當(dāng)前值對應(yīng)的行數(shù)+當(dāng)前值對應(yīng)的列數(shù)-最大匹配值) * 當(dāng)前值
當(dāng)然前提是這幾個位置都允許填
我們可以直接枚舉最大值K,跑多次二分圖,然后計算每次貢獻得到答案
不過,每種權(quán)值互相不影響,可以建立多個二分圖一次跑完
代碼:
#include<bits/stdc++.h> #define debug(a,b) printf("%s = %d\n",a,b); typedef long long ll; using namespace std; //Fe~Jozky const ll INF_ll=1e18; const int INF_int=0x3f3f3f3f; inline ll read(){ll s=0,w=1ll;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1ll;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10ll+((ch-'0')*1ll),ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w; } const int maxn=3e3+9; int a[maxn],b[maxn]; vector<int>g[maxn]; int match[maxn]; bool vis[maxn]; ll ans; int n,m,k; bool dfs(int x){for(int v:g[x]){if(vis[v])continue;vis[v]=1;if(!match[v]||dfs(match[v])){match[v]=x;return 1;}}return 0; } int main() {cin>>n>>m>>k;for(int i=1;i<=n;i++)cin>>a[i];for(int j=1;j<=n;j++)cin>>b[j];while(m--){int x,y;cin>>x>>y;if(a[x]==b[y])//如果該行最大值等于列最大值 g[x].push_back(y);}for(int i=1;i<=n;i++){memset(vis,0,sizeof(vis));dfs(i);}for(int i=1;i<=n;i++)//沒有優(yōu)化的結(jié)果 ans+=a[i]+b[i];for(int i=1;i<=n;i++)if(match[i])ans-=b[i];//可以省掉b[i] cout<<ans; }總結(jié)
以上是生活随笔為你收集整理的Minimum grid的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 孕期抑郁症的症状
- 下一篇: 环磷酰胺治疗肾病方案