[JZOJ2701] 【GDKOI2012模擬02.01】矩陣
題目
題目大意
給你一個矩陣,然後你需要構造一個等長等寬的矩陣,其中矩陣的每一個數字都有一個固定的範圍
。
然後要使得行的和之間的差,列的和之間的差,的最大值最小。
思考歷程
一開始見到這題時,我的心情是崩潰的。
為什麼呢?因為這題似乎暴力都不能做……
感覺上一定有什麼特別的結論或者是規律,但是時間不是很充足,所以我還是沒有想出來。
比賽之後……
老王跑進小機房,大聲地喊道:“這題可以網路流!!!”
誒,網路流?
比賽時的確沒有往這個方向考慮,然後考慮的一下……並沒有卵用啊……
正解
的確是網路流……
當我們見到不會做的題目的時候,應該往這三個方向考慮:DP、貪心、網路流。
這題的資料範圍似乎不大(實際上是放屁!),好像不能DP,貪心又想不出來……
於是我們選擇網路流!
首先,看到這題最大值最小,果斷二分!
我們二分一個答案
,現在問題轉換成了構造一個矩陣,使得行、列的差都小於
首先我們判定這時的
是否存在解。
有一個神奇的方法:對於每一行、每一列,我們都可以得到一個取值範圍。我們分別通過行、列,得到整個矩陣的取值範圍。然後我們看看用兩種方式得出來的取值範圍是否有交集,如果有,那麼一定能夠出解,否則不能。
具體怎麼證明……
勉強感性理解一下吧。我們有了這個取值範圍,那麼在這個取值範圍裡面一定有一種可行的方案。這個東西可以用腦子強行構造出來。所以說,如果行和列有交集,那麼就有可行的方案了……好草率……
其實第一次切這題的時候根本就沒有這樣判斷,在每次判斷時我直接跑可行流,速度奇慢,不過還是過了(比加了這個優化的老王還快,嘿嘿嘿)
求出了第一問的答案,現在我們考慮如何構造這個矩陣。
然後這題我們要用有上下界的網路流來做。
先說說怎麼建模:
對於每個行和每個列,我們都建立一個節點,並且還要設立源點
,匯點
。
對於行和列
和
,我們建立一條從
到
的邊,容量設為
對於每個行
,我們建立一條從
到
的邊,容量設為
。其中
表示這一行的和。
對於每個列
,我們建立一條從
到
的邊,容量設為
。其中
表示這一列的和。
(如果下界小於
,那我們就將就將下界設為
)
然後我們對這個圖跑一遍上下界的網路流,
答案就是每一行和每一列之間的流量了。
具體怎麼理解,其實我覺得,理解網路流一般都是用感性理解。
首先,每一個點只會影響一行一列,所以對於每行每列之間建立一條邊,就代表這個點。
我們要使得每行的差、每列的差都小於
,所以每行、每列的取值範圍就出來了。當然由於流量不會是負數,所以我們將負數補為
。
所以我們跑一遍可行流就可以了。
然後就是一個非常非常重要的問題,可行流怎麼跑呢?
先說無源無匯的上下界可行流
對於一條弧
,假設它的流量範圍是
。
我們希望它的流量在這個範圍,所以流量至少為
。所以我們先強制把它們的流量變成
,那麼殘餘的流量是
。
然後我們發現這麼簡單粗暴肯定是不可以的,因為我們都知道,網路流有流量平衡,就是流入量等於流出量。
在建圖的時候,我們將每一條弧的流量設為上界和下界的差,相當於已經強制性地將下界的流量流到了過去。
那麼我們考慮新增一些附加弧。對於一個點
,我們定義
表示所有流入量減流出量。
上邊在建圖的時候,對於邊
範圍
,則d[u]-=a,d[v]+=a
然後,在粗暴地將這些弧塞流量過後,列舉
,
如果
,則有流量流入
,所以從
向
建立一條容量為
的弧。
如果
,則有流量流出
,所以從
向
建立一條容量為
的弧。
其中
和
分別為虛源點和虛匯點,不要和
和
混淆!
然後我們就從
開始,跑一遍最大流,如果每一條附加邊都滿流,那麼此圖存在可行流。
跑完最大流之後,如果存在可行流,每一條邊的實際流量為它此時的流量加上下界的流量。
再說有源有匯上下界可行流
大部分的其實差不多,但我們要另外注意,
和
是不滿足流量平衡的!
如何解決這個問題?直接從
向
連一條容量為無限大的邊。
那麼就轉換成了之前的問題。
跑最大流的時候還是從
開始。
然後就是詭異的時間複雜度……
眾所周知,網路流的時間複雜度一直都很玄學。所以網路流基本沒用複雜度可言。
看看這題,一共有
條邊,有
的點,並且這只是原圖上的。
我們還要轉換模型來求上下界網路流呢!
所以邊的數量超多,不過由於網路流玄學的複雜度,我還是以非常優秀的時間跑過了。
程式碼
using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 200
#define M 200
int n,m;
int a[N+1][M+1];
int rsum[N+1],csum[M+1];
int L,R;
struct EDGE{
int to,c;
EDGE *las;
} e[1000001];
int ne;
EDGE *last[N+M+2+2+10];
inline void link(int u,int v,int c){
e[++ne]={v,c,last[u]};
last[u]=e+ne;
}
#define rev(ei) (e+(int((ei)-e)^1))
int ss,tt,S,T,nr[N+1],nc[M+1];//nr表示列的編號,nc表示行的編號
int in[N+M+2+2+10];
EDGE *p[N+1][M+1];//表示某行某列對應的邊
inline int sap(int,int);
inline void work(int);
inline bool ok(int);
int main(){
// freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
scanf("%d",&a[i][j]),rsum[i]+=a[i][j],csum[j]+=a[i][j];
scanf("%d%d",&L,&R);
for (int i=1;i<=n;++i)
nr[i]=i;
for (int i=1;i<=m;++i)
nc[i]=n+i;
S=n+m+1,T=n+m+2;
ss=n+m+3,tt=n+m+4;
int l=0,r=1000000000,res=-1;
while (l<=r){
int mid=l+r>>1;
if (ok(mid))
r=(res=mid)-1;
else
l=mid+1;
}
printf("%d\n",res);
work(res);
for (int i=1;i<=n;++i){
for (int j=1;j<=m;++j)
printf("%d ",p[i][j]->c+L);
printf("\n");
}
return 0;
}
EDGE *cur[N+M+2+2+10];
int gap[N+M+2+2+10],h[N+M+2+2+10];
相關推薦
[JZOJ2701] 【GDKOI2012模擬02.01】矩陣
題目
題目大意
給你一個矩陣,然後你需要構造一個等長等寬的矩陣,其中矩陣的每一個數字都有一個固定的範圍
[
L
【GDKOI2012模擬02.01】數字
想了2個小時。。。都想到數位DP去了,雖然沒打(但是我瘋了) 打表找規律。比賽時打了個表發現每九個的D()都是一迴圈(1~9) 然後想著怎麼做,先打了個暴力然後在想,沒想到的是: 如果x為喜歡的數的話,那麼x+22680也是喜歡的數。 為什麼? 設x=a·D(a),那麼x+22680
[JZOJ2702] 【GDKOI2012模擬02.01】探險
題目
題目大意
給你一個每條邊正反權值不一定相同的無向圖,求起點為
1
1
1點的最小環。
[JZOJ2700] 【GDKOI2012模擬02.01】數字
題目
題目大意
其實這題的題目大意非常簡練,所以我認為我不用解釋了。
思考歷程
首先亂推了一波,然後什麼東西都沒有發現。 於是想想
D
JZOJ5944. 【NOIP2018模擬11.01】信標
題意:
資料範圍:
對於前
20
20
20% 的資料,
JZOJ-senior-5943. 【NOIP2018模擬11.01】樹
Time Limits: 1000 ms Memory Limits: 262144 KB
Description
Input
第一行一個整數 n 表示序列長度, 接下來一行 n 個整數描述這個序列. 第三行一個整數 q 表示操作次數, 接下來 q 行每行一次操作, 格
JZOJ-senior-5941. 【NOIP2018模擬11.01】乘
Time Limits: 2000 ms Memory Limits: 262144 KB
Description
Input
Output
Sample Input
Sample Input1: 4 3 9 6 5 8 7 7
Sample I
jzoj5943. 【NOIP2018模擬11.01】樹(線段樹)
5943. 【NOIP2018模擬11.01】樹
Description
Input
第一行一個整數 n 表示序列長度, 接下來一行 n 個整數描述這個序列.
第三行一個整數 q 表示操作次數, 接下來 q 行每行一次操作, 格式同題目描述.
Output
輸
【NOIP2018模擬11.01】樹
題目
描述
題目大意
維護一個序列,支援三種操作:
1、修改一段區間,將這段區間內的所有數都andandand一個數。
2、詢問區間和。
3、詢問區間兩兩相加的平方和。
N≤10000N\leq 10000N≤10000
思路
顯然是一道資料結構題。
毋
JZOJ 5943. 【NOIP2018模擬11.01】樹
題目
對於 100% 的資料,n,q≤105n, q ≤ 10^5n,q≤105,ai≤109,ai ≤ 10^9,ai≤109,$ k ≤ 2^30,1≤l≤r≤n., 1 ≤ l ≤ r ≤ n.,1≤l≤r≤n.
題解
每個數多被減30次。
線段樹維護,
JZOJ5944.【NOIP2018模擬11.01】信標
PROBLEM
建立最少的信標,使得任意兩個點到至少一個信標的距離不同
SOLUTION
當n>1時,信標的個數>0,於是我們可以列舉其中一個信標的位置,將這個樹的根就定為這個點,那麼點就分層互不影響。
考慮當我們在根上放信標後,我們在一個點上放信標,對於它的子樹
[JZOJ5899]【NOIP2018模擬10.6】資源運輸【矩陣樹定理】【圖論】
Description
給定一個n個點,m條邊的帶權無向圖。 定義這個圖的一個生成樹的權值為生成樹上邊權的乘積。 求所有生成樹權值的平均值,答案對998244353取模。 2<=n<=300,n-1<=m<=1000
Solution
平均值=和/總數
jzoj5899 【NOIP2018模擬10.6】資源運輸 (矩陣樹定理)
描述
n<=300,給定有權邊,求生成樹大小和所有生成樹邊權乘積和。
要點
基爾霍夫矩陣:
c
[
jzoj 5899. 【NOIP2018模擬10.6】資源運輸 矩陣樹定理
Description
Input
Output
Sample Input
3 2
1 3 5
2 1 6
Sample Output
30
樣例說明:
顯然m=n-1時,只有一種選擇方法,優秀程
【ROS機器人作業系統初探索02.01】MoveIt!
安裝的部分我就省略了,跟著官網的步驟來就可以了(需要詳細翻譯步驟的話,可以留言,需要的人多的話,我就出個翻譯教程),第二部分學習完之後先不要跳到MoveIt!Setup Assistant tutorial,先按照它側目錄的步驟走,不然可能有一些需要tutorial裡面需要用
jzoj5141 【NOI2017模擬6.12】說無可說
題目 display nbsp stdout hid sed targe view n) 傳送門:https://jzoj.net/senior/#main/show/5141
【題目大意】
給出n個字符串,求有多少組字符串之間編輯距離為1~8。
n<=200,∑|S
【NOIP2017模擬8.5】隊伍統計
優先級 con isp pla cnblogs noip 技術分享 freopen 100%
Description
現在有n個人要排成一列,編號為1->n 。但由於一些不明原因的關系,人與人之間可能存在一些矛盾關系,具體有m條矛盾關系(u,v),表示編號
【NOI2015模擬8.14】A+B
std out 一個 blog sam 數據 -a spl stream
Description
對於每個數字x,我們總可以把它表示成一些斐波拉切數字之和,比如8 = 5 + 3, 而22 = 21 + 1,因此我們可以寫成 x = a1 * Fib1 + a2
【NOIP2017模擬8.8】Trip
關系 pan 根據 大於 二叉 計算 我們 else freopen
Description
多年之後,worldwideD厭倦競爭,隱居山林。 他的家鄉開始發展起了旅遊業,在一條很長的主幹道上,有N個旅遊景點,按順序編號為1到N。根據遊客們
[jzoj]2938.【NOIP2012模擬8.9】分割田地
script 連通 分配 mathjax cnblogs 沒有想到 -1 str 需要 Link
https://jzoj.net/senior/#main/show/2938
Description
地主某君有一塊由2×n個柵格組成的土地,有k個