題目描述
«問題描述:
假設乙個試題庫中有n道試題。每道試題都標明了所屬類別。同一道題可能有多個類別屬性。現要從題庫中抽取m 道題組成試卷。並要求試卷包含指定型別的試題。試設計乙個滿足要求的組卷演算法。
«程式設計任務:
對於給定的組卷要求,計算滿足要求的組卷方案。
輸入輸出格式
輸入格式:
第1行有2個正整數k和n (2 <=k<= 20, k<=n<= 1000)
k 表示題庫中試題型別總數,n 表示題庫中試題總數。第2 行有k 個正整數,第i 個正整數表示要選出的型別i的題數。這k個數相加就是要選出的總題數m。接下來的n行給出了題庫中每個試題的型別資訊。每行的第1 個正整數p表明該題可以屬於p類,接著的p個數是該題所屬的型別號。
輸出格式:
第i 行輸出 「i:」後接型別i的題號。如果有多個滿足要求的方案,只要輸出1個方案。如果問題無解,則輸出「no solution!」。
搞懂了這題,會對最大流有乙個更透徹的理解
首先,這題是乙個與匹配有關的題,遇到有關匹配的題,我們可以先聯想網路流
為什麼呢?因為最大流的核心是限制,而匹配類題目經常和限制有關(一道題只能選一次,這就是限制),所以我們使用最大流進行求解
這題需要求的是匹配方案,可能剛開始會比較難理解,那麼我們先解決 此問題是否有解這個子問題先
怎麼知道是否有解呢?我們知道,可以求最大匹配數,若比要求的匹配數小,則無解。這實際上是乙個二分圖多重匹配問題,可以用最大流求解:
建模思路: 源點連一部,容量為要求的匹配數,按匹配條件連線一部和二部,容量為inf,二部連匯點,容量為要求匹配數,最大流即可求出匹配數。畫圖即可很快得到證明。
此題中,一部為試題,容量都為1(限制每題只能用一次),二部為題類,容量為所需題目數
知道了有解,我們怎麼求解方案呢?
回想一下最大流(我用的是dinic)的執行過程,聯絡所學,我們知道:最大流有乙個後悔機制,即更新一條弧的剩餘容量是,同事更新反向邊的剩餘容量,**表現在這:
int dinic(int u,int flow)
}return flow - rest;
}
我們可以利用這一點求方案
試想,如果試題庫 \(s\) 中有一題 \(r\) ,那麼最大流一定從這\(r-->s\)這條弧走過過,換言之,這條弧一定對最大流量有所貢獻
既然正邊有所貢獻,那麼依據後悔機制,其反邊容量不就不為0了嗎?
我們從試題庫出發,遍歷所有連\(t\)的反邊(連向題目),若某邊不為0,則被連的題目一定被此試題庫選中
for(int u = 1 + numl;u <= numr + numl;u++)
}printf("\n");
}
#include#include#include#include#include#define ll long long
using namespace std;
int rd()
while(c >= '0' && c <= '9')
return flag * out;
}const int maxn = 10019,inf = 1e9;
int numr,numl,tot,nume = 1;
int need[maxn];
int s,t,maxflow;
int head[maxn];
struct nodee[maxn << 2];
void add(int u,int v,int dis)
int lev[maxn];
bool bfs()}}
return 0;
}int dinic(int u,int flow)
}return flow - rest;
}int main()
int num;
for(int i = 1;i <= numl;i++)
}int flow = 0;
while(bfs())
if(maxflow < tot)
for(int u = 1 + numl;u <= numr + numl;u++)
}printf("\n");
}return 0;
}
題解 P2763 試題庫問題 網路流
考慮乙個試題要被加入進答案的集合有什麼條件?就這兩種且的限制,所以我們用串聯的方式連線 型別點 和 作用點 判斷無解就判斷容量是否滿了。輸出方案就輸出有流量的邊的終點。winlere include include include include includeusing namespace std...
洛谷 P2763 試題庫問題
問題描述 假設乙個試題庫中有n道試題。每道試題都標明了所屬類別。同一道題可能有多個類別屬性。現要從題庫中抽取m 道題組成試卷。並要求試卷包含指定型別的試題。試設計乙個滿足要求的組卷演算法。程式設計任務 對於給定的組卷要求,計算滿足要求的組卷方案。輸入格式 第1行有2個正整數k和n 2 k 20,k ...
P2763 試題庫問題 最大流
原題 題解 其實就是就是n個試題和k配對。建圖方法 s連i i n j連t j k 且邊的流量是a i 如題連i j就行了。跑一邊最大流,從k列舉,輸出答案。然而洛谷上要英文冒號。include define inf 0x7fffffff using namespace std const int ...