Time Limit: 15000MS | Memory Limit: 65536K | |
Total Submissions: 2957 | Accepted: 993 | |
Case Time Limit: 2000MS |
Description
Input
Output
Sample Input
4 2 1 2 2 1 2 2 2 3 2 3 4 1 2 3 4
Sample Output
2 1 2 2 1 2 1 3 1 4
Hint
Source
/* (1)一开始以为是二分图的最大匹配,于是就是一个个尝试将每个女孩在原始匹配中的前驱改为当前喜欢这个女孩 的男孩,然后看能否为那个"被甩"的男孩找到增广路径,如果找得到,那么喜欢这个女孩的男孩就可以将这个女 孩记为自己的可行方案.这么做理论上是可行的,但是复杂度比较高,应为匈牙利算法的时间复杂度是O(n ^ 3), 加上要为每个女孩执行一次,所以最终的时间复杂度是O(n ^ 4),所以超时是必然. (2)后来看了Discuss的讨论,可以扩展到求强连通分量.那么可以这样建图:如果1-sonN,作为图中男孩的结点,sonN + 1 - sonN + sonN作为图中女孩的结点,如果男孩i喜欢女孩j则ij之间连一条有向边,另外对于原始匹配i,j j与i之间连 一条有向边.这样对新图求强连通分量,对于某个强连通分量中的所有男孩i以及女孩j,如果i喜欢j,则j作为i的可行方案 (3)为什么强连通分量映射到可行方案呢?因为这个子图里任何两个点都是可达的,所以任何男孩可以随意算则他喜欢的 女孩儿不会导致其他男孩找不到自己喜欢的女孩 (4)强连通分量的计算用到了tarjan算法 */ #include <iostream> #include <algorithm> #include <vector> #include <stack> #define MAXN 2005 #define maxv(a, b) ((a) >= (b) ? (a) : (b)) #define minv(a, b) ((a) <= (b) ? (a) : (b)) using namespace std; struct s { vector<int> vec; }graph[MAXN * 2 + 1]; int sonN; vector<int> res[MAXN + 1]; stack<int> stackk; bool processed[MAXN * 2 + 1], inStack[MAXN * 2 + 1], tarjanv[MAXN * 2 + 1]; int id[MAXN * 2 + 1], low[MAXN * 2 + 1], index; int tempList1[MAXN + 1], len1; bool tempList2[MAXN + 1]; bool compare(const int &v1, const int &v2) { return v1 <= v2; } //寻找curid所在的强连通分量 void tarjan(int curid) { tarjanv[curid] = true; id[curid] = low[curid] = ++index; stackk.push(curid); inStack[curid] = true; vector<int>::iterator iter = graph[curid].vec.begin(); for(; iter != graph[curid].vec.end(); iter++) { int toid = *iter; if(processed[toid]) continue; if(!tarjanv[toid]) { tarjan(toid); low[curid] = minv(low[curid], low[toid]); } else if(inStack[toid]) low[curid] = minv(low[curid], id[toid]); } //find a strong connected componet if(id[curid] == low[curid]) { int toid; len1 = 0; memset(tempList2, 0, sizeof(tempList2)); while(true) { toid = stackk.top(); stackk.pop(); inStack[toid] = false; if(toid <= sonN) tempList1[len1++] = toid; else tempList2[toid - sonN] = true; processed[toid] = true; if(toid == curid) break; } for(int i = 0; i < len1; i++) { int fromid = tempList1[i]; vector<int>::iterator iter = graph[fromid].vec.begin(); for(; iter != graph[fromid].vec.end(); iter++) { int toid = *iter; if(tempList2[toid - sonN]) res[fromid].push_back(toid - sonN); } } } } int main() { int i, j; scanf("%d", &sonN); for(i = 1; i <= sonN; i++) { int gnum; int girl; scanf("%d", &gnum); for(j = 1; j <= gnum; j++) { scanf("%d", &girl); graph[i].vec.push_back(girl + sonN); } } for(i = 1; i <= sonN; i++) { scanf("%d", &j); graph[j + sonN].vec.push_back(i); } for(i = 1; i <= sonN; i++) { if(!processed[i]) { while(!stackk.empty()) stackk.pop(); memset(inStack, 0, sizeof(inStack)); memset(tarjanv, 0, sizeof(tarjanv)); index = 0; tarjan(i); } } for(i = 1; i <= sonN; i++) { sort(res[i].begin(), res[i].end(), compare); vector<int>::iterator iter = res[i].begin(); printf("%d", res[i].size()); for(; iter != res[i].end(); iter++) printf(" %d", *iter); printf("/n"); } return 0; }