二分 上下界網路流 BZOJ2406 矩陣

2021-08-03 13:02:55 字數 1681 閱讀 7051

題面在這裡

好題,好題啊!!

此題乍一看好像和網路流完全沒有關聯

其實暗藏玄機

題面不講人話……

其實就是使矩陣a-b的每一行每一列的絕對值的最大值最小

顯然可以看出要二分

列舉乙個當前的最大值m,則下式恆成立: |s

ai−s

bi|≤

m 等價於下式: sa

i−m≤

sbi≤

sai+

m (有同學可能不能理解,建議從絕對值的幾何意義考慮)

然後把每個b矩陣中的數字看作流量

每一行、每一列看作乙個點 因為s

ai−m

≤sbi

≤sai

+m所以s→

i[sa

i−m,

sai+

m](內表示流量範圍) 同理s

→j[s

aj−m

,saj

+m]

又有每個點的取值為[l,r]

即單個行與列之間的流量聯絡在[l,r]內 i→

j[l,

r]然後就套用「有源匯上下界可行流」

示例程式:

#include

#include

#include

using

namespace

std;

const

int maxn=405,maxe=200005,inf=0x3f3f3f3f;

int n,m,s_i[maxn],s_j[maxn],l,r,s,t,ss,tt;

int tot,lnk[maxn],son[maxe],nxt[maxe],cap[maxe],flw[maxe];

inline

char nc()

inline

int red()

while ('0'

<=ch&&ch<='9') res=res*10+ch-48,ch=nc();

return res*f;

}inline

void add(int x,int y,int z)

int d[maxn],pos[maxn],que[maxn],tmp[maxn];

bool bfs(int s,int t)

int dfs(int x,int flow,int t)

return res;

}int dinic(int s,int t)

return res;

}bool check(int mid)

for (int j=1;j<=m;j++)

for (int i=1;i<=n;i++)

for (int j=1;j<=m;j++)

add(i,j+n,r-l),tmp[i]-=l,tmp[j+n]+=l;

int blc=0;

for (int i=1;i<=n+2;i++)

if (tmp[i]>0) add(ss,i,tmp[i]),blc+=tmp[i];else add(i,tt,-tmp[i]);

add(t,s,inf);

return blc==dinic(ss,tt);

}int main()

printf("%d",ans);

return

0;}

bzoj2406 矩陣 二分 有上下界可行流

題目描述 輸入第一行兩個數n m,表示矩陣的大小。接下來n行,每行m列,描述矩陣a。最後一行兩個數l,r。輸出第一行,輸出最小的答案 樣例輸入 2 20 1 2 10 1 樣例輸出1題解 二分 有上下界可行流 題目一眼二分,問題轉化為判斷是否存在一種填數方式滿足行之和的差與列之和的差都不超過mid。...

BZOJ2406矩陣 有上下界的可行流 二分答案

第一行兩個數n m,表示矩陣的大小。接下來n行,每行m列,描述矩陣a。最後一行兩個數l,r。第一行,輸出最小的答案 2 20 1 2 10 1 1對於100 的資料滿足 n,m 200,0 l r 1000,0 aij 1000 要求最大值最小,顯然二分答案。每次二分乙個 mid 設每行或每列的 a...

BZOJ2406 矩陣 二分 有上下界的可行流

第一行兩個數n m,表示矩陣的大小。接下來n行,每行m列,描述矩陣a。最後一行兩個數l,r。第一行,輸出最小的答案 2 20 1 2 10 1 1對於100 的資料滿足 n,m 200,0 l r 1000,0 aij 1000 題解 容易想到二分,並且這個和式可以拆成 sum a sum b 的形...