一年一度的綜藝節目《中國新**》又開始了。
zayid從小就夢想成為一名程式設計師,他覺得這是乙個展示自己的舞台,於是他毫不猶豫地報名了。
題目描述
輕車熟路的zayid順利地通過了海選,接下來的環節是導師盲選,這一階段的規則是這樣的:
總共n名參賽選手(編號從1至n)每人寫出乙份**並介紹自己的夢想。接著由所有導師對這些選手進行排名。
為了避免後續的麻煩,規定不存在排名並列的情況。
同時,每名選手都將獨立地填寫乙份志願表,來對總共m位導師(編號從1至m)作出評價。
志願表上包含了共m檔志願。
對於每一檔志願,選手被允許填寫最多c位導師,每位導師最多被每位選手填寫一次(放棄某些導師也是被允許的)。
在雙方的工作都完成後,進行錄取工作。
每位導師都有自己戰隊的人數上限,這意味著可能有部分選手的較高志願、甚至是全部志願無法得到滿足。節目組對」
前i名的錄取結果最優「作出如下定義:
前1名的錄取結果最優,當且僅當第1名被其最高非空志願錄取(特別地,如果第1名沒有填寫志願表,那麼該選手出局)。
前i名的錄取結果最優,當且僅當在前i-1名的錄取結果最優的情況下:第i名被其理論可能的最高志願錄取
(特別地,如果第i名沒有填寫志願表、或其所有志願中的導師戰隊均已滿員,那麼該選手出局)。
如果一種方案滿足『『前n名的錄取結果最優』』,那麼我們可以簡稱這種方案是最優的。
舉例而言,2位導師t老師、f老師的戰隊人數上限分別都是1人;2位選手zayid、duckd分列第1、2名。
那麼下面3種志願表及其對應的最優錄取結果如表中所示:
可以證明,對於上面的志願表,對應的方案都是唯一的最優錄取結果。
每個人都有乙個自己的理想值si,表示第i位同學希望自己被第si或更高的志願錄取,如果沒有,那麼他就會非常沮喪。
現在,所有選手的志願表和排名都已公示。巧合的是,每位選手的排名都恰好與它們的編號相同。
對於每一位選手,zayid都想知道下面兩個問題的答案:
在最優的錄取方案中,他會被第幾志願錄取。
在其他選手相對排名不變的情況下,至少上公升多少名才能使得他不沮喪。
作為《中國新**》的實力派**手,zayid當然輕鬆地解決了這個問題。
不過他還是想請你再算一遍,來檢驗自己計算的正確性。
每個測試點包含多組測試資料
第一行2個用空格隔開的非負整數t;c,分別表示資料組數、每檔志願最多允許填寫的導師數目。
接下來依次描述每組資料,對於每組資料:
第1行兩個用空格隔開的正整數n;m。
n;m分別表示選手的數量、導師的數量。
第2行m個用空格隔開的正整數:其中第i個整數為bi。
bi表示編號為i的導師戰隊人數的上限。
第3行至第n+2行,每行m個用空格隔開的非負整數:其中第i+2行左起第j個數為ai,j
ai,j表示編號為i的選手將編號為j的導師編排在了第ai,j志願。特別地,如果ai,j=0,則表示該選手沒有將該導師填入志願表。
在這一部分,保證每行中不存在某乙個正數出現超過c次(0可能出現超過c次),同時保證所有ai,j<=m。
第n+3行n個用空格隔開的正整數,其中第i個整數為si
si表示編號為i的選手的理想值。
在這一部分,保證si<=m。
t<=5,m<=n<=200,bi<=n
按順序輸出每組資料的答案。對於每組資料,輸出2行:
第1行輸出n個用空格隔開的正整數,其中第i個整數的意義為:
在最優的錄取方案中,編號為i的選手會被該檔志願錄取。
特別地,如果該選手出局,則這個數為m+1。
第2行輸出n個用空格隔開的非負整數,其中第i個整數的意義為:
使編號為i的選手不沮喪,最少需要讓他上公升的排名數。
特別地,如果該選手一定會沮喪,則這個數為i。
3 5
2 21 1
2 21 2
1 12 2
1 11 2
1 22 1
2 21 1
0 10 1
2 2
2 1
1 01 2
0 11 3
0 1
三組資料分別與【題目描述】中的三個**對應。
對於第1 組資料:由於選手1 沒有填寫第一志願,所以他一定無法被第一志願錄取,也就一定會沮喪。
選手2 按原排名就不沮喪,因此他不需要提公升排名。
對於第2 組和第3 組資料:1 號選手都不需要提公升排名。
而希望被第一志願錄取 的2 號選手都必須公升到第1 名才能如願。
顯然是網路流。
對於第一問,每個導師向匯點連一條容量\(b_i\)的邊。然後依次考慮每個選手。對於某個選手,先從源點向他連一條容量為1的邊,然後從高到低考慮每個志願,每次向乙個志願中所有老師連邊,判斷流量是否增加,如果增加,答案即是這個志願,否則再將這些邊刪掉。
對於第二問,由於\(i\)要實現夢想,因此他必須被前\(s_i\)志願錄取。我們把選手\(i\)與這些志願中包含的導師全部進行連邊。接著,我們依次檢查第\(1,…,i-1\)名選手的志願是否會發生變化:檢查選手\(k\)時,只需要連\(k\)在第一小問中求出的答案志願的邊即可。如果檢查到\(k\)時增廣失敗,則表示\(i\)不能完成夢想,一旦出現這種情況,則立刻可知\(i\)選手第二問的答案即為\(i-k\)。
很顯然,這個演算法的複雜度是\(ο(f(n,nc)n)\)的。其中\(f(n,m)\)表示的是\(ο(n)\)個點\(ο(m)\)條邊的二分圖跑匹配的複雜度。用\(dinic\)演算法最終的複雜度為\(o(n^c)\)。
需要注意的是,第一問中求出每個選手的答案之後,必須將非答案志願中的邊都刪掉,否則會使邊數達到\(o(mnc)\)的級別。
#include#define maxn 410
#define inf 0x3f3f3f3f
namespace io
inline int qr()
while(ch>='0'&&ch<='9')
return rev?-x:x;}
}using namespace io;
using namespace std;
struct edgee[100010];
struct datae[201];
int head[maxn],cnt=1,s,t,d[maxn];
inline void add_edge(int from,int to,int cap)
inline void init()
queueq;
inline bool bfs()
} }return d[t]!=-1;
}int dfs(int u,int now)
} if(!flow)d[u]=-1;
return flow;
}int q,c,n,m,b[maxn],s[maxn],ans1[210],ans2[210];
vectora[210][210];
inline void build()
inline void solve1()
cnt=e[i-1].cnt;
for(int k=1;k<=t;k++)head[k]=e[i-1].head[k];
} if(!ans1[i])ans1[i]=m+1;
e[i].cnt=cnt;
for(int j=1;j<=t;j++)e[i].head[j]=head[j];
for(int j=1;j<=cnt;j++)e[i].e[j]=e[j]; }}
inline void solve2()
build();now=0;ans2[i]=i;
add_edge(s,i,1);
for(int j=1;j<=s[i];j++)
}while(bfs())now+=dfs(s,inf);
for(int j=1;j
while(bfs())now+=dfs(s,inf);
if(now==last) }}
}int x;
int main()
} for(int i=1;i<=n;i++)s[i]=qr();
solve1();solve2();
for(int i=1;i<=n;i++)printf("%d ",ans1[i]);
puts("");
for(int i=1;i<=n;i++)printf("%d ",ans2[i]);
puts("");
for(int i=1;i<=n;i++)
} }
return 0;
}
bzoj5251 2018多省省隊聯測 劈配
直接網路流模擬即可ac。可持久化 暴力 90分,可持久化 二分 30分,暴力加邊 二分 100分。我也很無奈啊。ivan便漲紅了臉,額上的青筋條條綻出,爭辯道,memcpy也是可持久化 memcpy!oier的事,當然是可持久化!接連便是難懂的話,什麼 可持久化無旋treap套線段樹啟發式合併 什麼...
BZOJ 5251 2018多省省隊聯測 劈配
題目大意 題解 要求最優的錄取方案,網路流。問每個人的排名至少上公升多少才能滿足期望,這個有二分性。二分 網路流判定,沒有加優化所以在某些 上會t。include include include include define pi acos 1 using namespace std struct ...
bzoj5250 2018多省省隊聯測 秘密襲擊
博主蒟蒻,目前還不會動態dp,所以下面說的是乙個並不優秀的暴力,我會補的!我們考慮按權值從大到小依次點亮每個點,相同權值可以同時點亮,每次點亮後,我們進行一次樹形揹包。處理出 f i j 表示i的子樹中有j個亮點的方案數,然後就ac了。有兩個小優化,乙個是將揹包的列舉上限設為min size x k...