UVA 10092 The Problem with the Problemsetter【二分图最大匹配变形 邻接矩阵实现最大匹配算法】

来源:互联网 发布:网络驱动怎么检查 编辑:程序博客网 时间:2024/05/22 00:55

题目大意:一名老师出题,要求出N种题型,每个题型要求出多少题给出;

                    现在有M道题(待选问题),每道题给出它可以被归类的题型;

                    问最后是否能按照要求出题,满足要求,输出1及每种题型对应待选问题,否则输出0

解题策略:这题初看思路与 UVA 11045 My T-shirt suits me http://blog.csdn.net/j_dark/article/details/8830539相同,

                    1, 由于每种题型有容量要求,故考虑将题型size拆成题型同为size的k道题(若该种题型要求出k道),

                           建立{题型拆后题,待选问题}二部图模型;

                    2,判别能否按要求出题——求出待选题目相对题型的最大匹配(逻辑上可理解为按照题型能够出多少题),与要求出题数比较,

                          感觉 上述最大匹配数<=要求出题数,未证明(网上都是网络流的报告,学过网络流后,估计会多一种理解。)

                    3,用sizeMatch[i]记录与题型拆后题匹配的待选问题,这部分如何输出详见注释。

                    4,用邻接矩阵练了下最大匹配算法,发现在输出答案与运算时间方面,和邻接表不是一个时间量级。


/*   UVA 10092 The Problem with the Problemsetter   AC by J_Dark   ON 2013/4/21   Time 0.334s  邻接矩阵还真是慢*/#include <iostream>#include <cstring>#include <string>#include <cstdio>const int maxn = 1005;using namespace std;/*   1.  proSizeNum 题型数   proNum  待选问题数   proSizeSum  一共需出题数(各题型数目之和)   2.  proSetNum[]  题型对应出题数       proMatch[] 与待选问题匹配的拆后题型问题       sizeMatch[]  与拆后题型问题匹配的待选问题       proMatch[]与sizeMatch[]不同!   3. 若一种题型要出第k种题,将一种题型拆成k种同题型题,建立拆后题型题——待选题二部图       pos[i]存放第i种题型题在无向图g中起始下标,终点为pos[i]+proSetNum[i]*/int proSizeNum, proNum, proSizeSum;int proSetNum[maxn], pos[maxn], g[maxn][maxn], proMatch[maxn], sizeMatch[maxn];bool visited[maxn];void Initial(){memset(g, 0, sizeof(g));pos[1] = 1;for(int i=2; i<=proSizeNum; i++){pos[i] = pos[i-1]+proSetNum[i-1];}}bool findPath(int u){for(int i=1; i<=proSizeSum; i++){if(g[u][i] && !visited[i]){visited[i] = true;if(sizeMatch[i] == -1 || findPath(sizeMatch[i])){sizeMatch[i] = u;            proMatch[u] = i;return true;}}}return false;}void MaxMatch(){for(int i=1; i<=proNum; i++)  proMatch[i] = -1;for(int i=1; i<=proSizeSum; i++)  sizeMatch[i] = -1;int maxMatch = 0;for(int i=1; i<=proNum; i++){if(proMatch[i] == -1){memset(visited, false, sizeof(visited));if(findPath(i))   maxMatch++;}}//若最大匹配数即最大可以出题数与要求出题数相同,则输出相应答案if(maxMatch == proSizeSum){cout << 1 << endl;    for(int i=1; i<=proSizeNum; i++){   //输出与第i种题型匹配的proSet[i]道待选题       for(int k=0; k<proSetNum[i]; k++){          if(k>0)  cout << " ";          cout << sizeMatch[pos[i]+k];       }       cout << endl;    }}else cout << 0 << endl;}///////////////////////////////////////////////////////////////int main(){while(cin >> proSizeNum >> proNum && (proSizeNum||proNum)){proSizeSum = 0;for(int i=1; i<=proSizeNum; i++){   cin >> proSetNum[i];   proSizeSum += proSetNum[i];}Initial();for(int i=1; i<=proNum; i++){int reachedNum;cin >> reachedNum;for(int j=0; j<reachedNum; j++){int v;cin >> v;//将一种题型v拆成k种题型为v题for(int k=0; k<proSetNum[v]; k++)   g[i][pos[v]+k] = v;}}MaxMatch();}//system("pause");return 0;}


原创粉丝点击