Hoj 14013 Translators’ Dinner 高斯消元 以后会明白的= =
// A solution can be found by solving a linear system over 𝔽₂, the field of two elements. I'll explain briefly how this is done. // // Suppose first that we have a valid matching plan of the translators. Every translator has exactly one language in common with his match. If we take for every translator the language he has in common with his match, then we get a multiset of languages, each of which occurs an even number of times. Conversely, if every translator chooses his favourite language from his two languages in such a way that every language is chosen an even number of times, then we can easily construct a matching from this: for each language L we simply pair up the translators who chose L. // // Now how do we know if such a choice of favourite languages exists? This turns out to be a simple matter of linear algebra: // // * For each translator j we create a variable x[j] denoting his choice: // 0 for the his first language in the input, 1 for the second language. // These variables together form a column vector x. // // * Let M denote the incidence matrix of the language graph. This is an n ⨉ m matrix where M[i][j] is 1 if translator j speaks language i and zero otherwise. // // * For each language i we let y[i] denote the number of translators that have language i as their first language. // // Now the variable vector x is valid if and only if Mx ≡ y (mod 2) holds. // The proof is left as an exercise to the interested reader. // // To give a simple example: if every entry in y is even, then every translator can simply choose his first language and we have a valid solution. In terms of linear algebra, we see that the equality M * 0 ≡ 0 ≡ y (mod 2) holds. // // This shows that the problem can be reduced to solving the linear system Mx = y over the field of two elements. // // Current implementation complexity: O(N * M^2). // (This can be improved upon, but this is fast enough given the bounds.) //可以通过求解一个线性系统来找到一个解决方案。我将简要介绍一下如何做到这一点。 // //假设我们有一个有效的翻译器匹配计划。每个翻译者都有一种与他的比赛相同的语言。如果我们为每个翻译人员提供与他的比赛相同的语言,那么我们得到一个多语言的语言,每个语言都发生了很多次。 相反,如果每个翻译者从他的两种语言中选择他最喜欢的语言,使得每种语言都被选择了很多次,那么我们可以很容易地从中构建一个匹配:对于每种语言L,我们简单地配对选择的翻译L. // //现在我们如何知道这样一种喜欢的语言的选择是否存在?这是一个简单的线性代数问题: // // *对于每个翻译器j,我们创建一个变量x [j],表示他的选择: //输入第一个语言为0,第二个语言为1。 //这些变量一起形成列向量x。 // // *令M表示语言图的入射矩阵。这是一个n⨉m矩阵,其中如果翻译者j说语言i,则M [i] [j]为1,否则为0。 // // *对于每种语言,我们让y [i]表示具有语言i作为其第一语言的翻译者的数量。 // //当且仅当Mx≡y(mod 2)成立时,变量向量x才有效。 //证明留给感兴趣的读者作为练习。 // //给出一个简单的例子:如果y中的每个条目都是偶数,那么每个翻译者都可以简单地选择他的第一语言,并且我们有一个有效的解决方案。在线性代数方面,我们看到等式M * 0≡0≡y(mod 2)成立。 // //这表明这个问题可以减少到在两个元素的领域中求解线性系统Mx = y。 // //当前实现复杂度:O(N * M ^ 2)。 //(这可以改进,但这是足够快的给定边界。)
Let languages be nodes and translators be edges. Given a connected graph, give a matching of the edges, or report that no such matching exists. Theorem: a matching exists if and only if the number of edges is even. A proof of this theorem often leads to an algorithm, or vice versa! One solution uses an almost spanning tree, or AST. An AST on a graph G is a subtree of G which contains all vertices, except possibly some vertices of degree 1, which connect directly to the tree. Any spanning tree is also an AST. Any graph with an AST is connected. Construct an AST T on the graph (by making a spanning tree). For a leaf l belongs to T, if there are at least two edges incident to l which are not in T; match them and remove them from the graph. Repeat until there are zero or one such edges left. One: match that edge with the edge that connects the leaf to the tree and remove both of them from the graph. Zero: remove the leaf from T (but not the graph). Repeat with a new leaf until T (and thus the graph) is empty. Because T is always an AST, this works. 语言是节点和翻译器的边缘。 给定连接图,给出边的匹配,或报告不存在这样的匹配。 定理:当且仅当边数为偶数时,匹配存在。 这个定理的证明往往导致一个算法,反之亦然! 一个解决方案使用几乎生成的树或AST。 图G上的AST是包含所有顶点的G的子树,除了可能的一些直接连接到树的1的顶点之外。 任何生成树也是一个AST。 连接了任何具有AST的图形。 在图上构造一个AST T(通过生成一个生成树)。 对于叶l属于T,如果有至少两个入射到l的边不在T中;匹配它们并从图中删除它们。 重复,直到剩下零或一个这样的边。 一个:将边缘与将叶连接到树的边缘匹配,并从图中删除它们。 零:从T中删除叶子(而不是图形)。 重复一个新的叶,直到T(因此图)为空。 因为T总是AST,所以这个工作。
//两种题解可能我还是太笨了- -
#include <iostream> #include <cassert> #include <vector> using namespace std; const int MAX_LANGUAGES = 100; const int MAX_TRANSLATORS = 200; int N, M; int languages[MAX_TRANSLATORS][2]; // store the linear system as an augmented matrix int linearSystem[MAX_LANGUAGES][MAX_TRANSLATORS + 1]; int x[MAX_TRANSLATORS]; int rowPivot[MAX_LANGUAGES]; int colPivot[MAX_TRANSLATORS]; // print function for debugging purposes: void printTheLinearSystem() { for (int i = 0; i < N; i++) { cerr << '['; for (int j = 0; j <= M; j++) { cerr << ' ' << linearSystem[i][j]; } cerr << " ]" << endl; } cerr << endl; for(int i=0;i<N;i++) printf("%d ",rowPivot[i]);printf("\n"); } int main() { // Step 1: read the input and initliaze the matrix cin >> N >> M; assert(N >= 2 && N <= MAX_LANGUAGES); assert(M >= 1 && M <= MAX_TRANSLATORS); for (int i = 0; i < N; i++) rowPivot[i] = -1; for (int j = 0; j < M; j++) colPivot[j] = -1; for (int j = 0; j < M; j++) { int A, B; cin >> A >> B; assert(A >= 0 && A < N); assert(B >= 0 && B < N); languages[j][0] = A; languages[j][1] = B; linearSystem[A][j] = 1; linearSystem[B][j] = 1; // the final column represents the target vector y: linearSystem[A][M] ^= 1; } for(int i=0;i<M;i++)printf("%d ",languages[i][x[i]]);printf("\n"); #ifndef ONLINE_JUDGE printTheLinearSystem(); #endif // Step 2: Gaussian elimination for (int curPivotCol = 0; curPivotCol < M; curPivotCol++) {//对于每个人 printf("curPivotCol:%d\n",curPivotCol); int curPivotRow = -1;//当前语言为-1 for (int i = 0; i < N; i++) { if (rowPivot[i] == -1 && linearSystem[i][curPivotCol] == 1) { curPivotRow = i; break; } }//找到他会的第一个语言为curPivotRow=i printf("curPivotRow:%d\n",curPivotRow); if (curPivotRow == -1) continue; rowPivot[curPivotRow] = curPivotCol;//会语言row的人是col //colPivot[curPivotCol] = curPivotRow;//col会选择语言row for (int i = 0; i < N; i++) { if (i == curPivotRow) continue; if (linearSystem[i][curPivotCol] == 1) {//对于会语言row的第二个语言 for (int j = 0; j <= M; j++) { linearSystem[i][j] ^= linearSystem[curPivotRow][j]; if(curPivotCol==0)printf("%d %d\n",curPivotRow,j); //会的变不会,不会的变会 } } } #ifndef ONLINE_JUDGE printTheLinearSystem(); #endif } // Step 3: find solution vector x for (int j = 0; j < M; j++) x[j] = 0; for(int i=0;i<M;i++)printf("%d ",x[i]);printf("\n"); for (int i = 0; i < N; i++) { if (rowPivot[i] != -1) { x[rowPivot[i]] = linearSystem[i][M];//会语言i的人不会,那么这个人选择语言0或1 } else if (linearSystem[i][M] != 0) {//会语言i的人为空,那么 cout << "impossible" << endl; return 0; } } for(int i=0;i<M;i++)printf("%d ",x[i]);printf("\n"); // Step 4: output a matching vector<int> perLanguage[MAX_LANGUAGES]; for (int j = 0; j < M; j++) { perLanguage[languages[j][x[j]]].push_back(j); } for (int i = 0; i < N; i++) { unsigned l = perLanguage[i].size(); assert(l % 2 == 0); for (unsigned j = 0; j < l; j += 2) { cout << perLanguage[i][j] << ' ' << perLanguage[i][j + 1] << endl; } } for(int i=0;i<M;i++)printf("%d ",languages[i][x[i]]);printf("\n"); return 0; }

浙公网安备 33010602011771号