匈牙利演算法
這是題目
因為是網路流24題網路流十分擅長這種求關係的題目,所以我們優先考慮寫網路流。
對於網路流一類的問題,我們優先開啟畫圖軟體思考如何建模。
首先我們先把這些題目與型別之間建一條邊:
接著再把這些無向邊變成有向邊,然後再加上源節點s與匯節點t,再把源節點與型別相連,把題目與匯節點相連:
這不就成了乙個標準的網路流模型嗎?
至於我是怎麼想出以上操作的……誒嘿~(試圖萌混過關.jpg)
話說這個不是標準套路嗎(小聲bb)
然後就該考慮如何設定邊的容量。
因為每道題只能被選擇一次,所以題目到t的邊的容量全部設為1。
設型別i
_ii
需要選擇 k
ik_i
ki 道題,那麼經過它流到匯點 t 的流量必須正好為 k
ik_i
ki 。
如果多於 k
ik_i
ki 的話代表你多選了一題,小於 k
ik_i
ki 的話代表已經沒有題目可以選擇了。
所以我們正好把s到型別i
_ii
的邊的容量設為 k
ik_i
ki,這樣你就不可能因為多選題目導致出現奇奇怪怪的錯誤。
最後就是型別到題目的邊了。
可以看出,只要你不把這些邊的容量設成小於1的數就行了。
因為題目到匯點 t 的邊容量為1,所以無論你把型別到題目的邊的容量設到多大,在最大流演算法中跑出來的結果都是一樣的(如果大到爆int、ll的話當我沒說/jk)
建圖之前,邊一定要初始化,可見網路流的建圖方式(我還暫時沒寫,有空補上)
網路流求出的最大流就是你選擇的題目數量,如果最大流不等於你要選擇的題目總和,那麼無解。
邊不要建反了/kk(某位反覆建反邊的蒟蒻感覺/kk)
#include
using
namespace std;
const
int n =
1e3+27;
const
int m =
2.1e4+27
;const
int inf =
2e9+7;
struct edge e[m <<1]
;int p[n]
,eid;
void
init()
void
insert
(int u,
int v,
int c)
void
addedge
(int u,
int v,
int c)
int s,t;
int cur[n]
,dep[n]
;queue<
int> q;
bool
bfs()}
}return dep[t]!=-
1;}int
dfs(
int u,
int flow)
int res =0;
for(
int i = cur[u]
;i !=-1
;i = e[i]
.fail)}}
if(res ==0)
return res;
}int
dinic()
return res;
}int n,k,m;
intmain()
for(
int v = k +
1;v <= k + n;
++ v)
}for
(int u = k +
1;u <= n + k;
++ u)if(
dinic()
!= m)
for(
int u =
1;u <= k;
++ u)
}printf
("\n");
}return0;
}
直接最大二分圖匹配,十分無腦。
但這不屬於網路流的範圍,本蒟蒻不給予任何思路與**上的參考。
試題庫問題
假設乙個試題庫中有n道試題。每道試題都標明了所屬類別。同一道題可能有多個類別屬性。現要從題庫中抽取 m 道題組成試卷。並要求試卷包含 指定型別的試題。試設計乙個滿足要求的組卷演算法。對於給定的組卷要求,計算滿足要求的組卷方案。由檔案input.txt提供輸入資料。檔案第1行有2個正整數n和k 2 k...
試題庫問題
網路流24題裡面的,這題應該不算難,建圖比較簡單,就是把源點和型別連一條流量為需求題的邊,把型別和對應的題連一條流量為1的邊,把題和匯點連一條流量為1 的邊,保證每道題只用一次。然後找型別和題之間滿流的邊,表示這題在裡面。include include include include using n...
試題庫問題
題目描述 假設乙個試題庫中有n道試題。每道試題都標明了所屬類別。同一道題可能有多個類別屬性。現要從題庫中抽取m 道題組成試卷。並要求試卷包含指定型別的試題。試設計乙個滿足要求的組卷演算法。對於給定的組卷要求,計算滿足要求的組卷方案。輸入格式 第1行有2個正整數k和n 2 k 20,k n 1000 ...