Sicily 1008. Translations

来源:互联网 发布:http js.zy.com 编辑:程序博客网 时间:2024/05/16 07:22

1008. Translations

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

Bob Roberts is in charge of performing translations of documents between various languages. To aid him in this endeavor his bosses have provided him with translation files. These files come in twos -- one containing sample phrases in one of the languages and the other containing their translations into the other language. However, some over-zealous underling, attempting to curry favor with the higher-ups with his initiative, decided to alphabetically sort the contents of all of the files, losing the connections between the phrases and their translations. Fortunately, the lists are comprehensive enough that the original translations can be reconstructed from these sorted lists. Bob has found this is most usually the case when the phrases all consist of two words. For example, given the following two lists: Language 1 Phrases Language 2 Phrases arlo zym bus seat flub pleve bus stop pleve dourm hot seat pleve zym school bus Bob is able to determine that arlo means hot, zym means seat, flub means school, pleve means bus, and dourm means stop. After doing several of these reconstructions by hand, Bob has decided to automate the process. And if Bob can do it, then so can you.

Input

Input will consist of multiple input sets. Each input set starts with a positive integer n, n 250, indicating the number of two-word phrases in each language. This is followed by 2n lines, each containing one two-word phrase: the first n lines are an alphabetical list of phrases in the first language, and the remaining n lines are an alphabetical list of their translations into the second language. Only upper and lower case alphabetic characters are used in the words. No input set will involve more than 25 distinct words. No word appears as the first word in more than 10 phrases for any given language; likewise, no word appears as the last word in more than 10 phrases. A line containing a single 0 follows the last problem instance, indicating end of input.

Output

For each input set, output lines of the form word1/word2 where word1 is a word in the first language and word2 is the translation of word1 into the second language, and a slash separates the two. The output lines should be sorted according to the first language words, and every first language word should occur exactly once. There should be no white space in the output, apart from a single blank line separating the outputs from different input sets. Imitate the format of the sample output, below. There is guaranteed to be a unique correct translation corresponding to each input instance.

Sample Input

4arlo zymflub plevepleve dourmpleve zymbus seatbus stophot seatschool bus2iv otasotas reec teg ec0

Sample Output

arlo/hotdourm/stopflub/schoolpleve/buszym/seativ/egotas/ecre/t
刚开始隐隐约约觉得要构图,但是在图这方面我的知识比较匮乏,只好试试硬着头皮DFS,也考虑到了剪枝,但由于没有构图,深搜的深度是n,TLE了。

参考了网上的题解,构图判断两图是否同构。

#include <algorithm>#include <iostream>#include <string>#include <stdio.h>#include <queue>#include <string.h>#include <vector>#include <iomanip>#include <map>#include <stack>#include <functional>#include <list>#include <cmath>using namespace std;#define MAX_N 30  // 最大点数struct Node {  // 点    string s;  // 点中信息    int match;  // 匹配点在另一张图中的编号    int inDegree;  // 入度    int outDegree;  // 出度    Node() {}    Node(string sIn, int m = -1, int i = 0, int o = 0) {        s = sIn;        match = m;        inDegree = i;        outDegree = o;    }};Node N1[MAX_N], N2[MAX_N];  // 图一图二的点bool G1[MAX_N][MAX_N], G2[MAX_N][MAX_N];  // 图一图二int n, n1, n2;  // n为题意n,n1为图一点数,n2为图二点数map<string, int> M1, M2;  // 图一图二字符串和下标的对应关系bool succeed;  // 是否搜到了答案void makeG() {    M1.clear();    M2.clear();    n1 = n2 = 0;    memset(G1, false, sizeof(G1));    memset(G2, false, sizeof(G2));    for (int i = 0; i < n; i++) {  // 建图一        string s1, s2;        cin >> s1 >> s2;        if (M1.find(s1) == M1.end()) {            M1[s1] = n1;            N1[n1] = Node(s1, -1, 0, 1);            n1++;        } else {            N1[M1[s1]].outDegree++;        }        if (M1.find(s2) == M1.end()) {            M1[s2] = n1;            N1[n1] = Node(s2, -1, 1, 0);            n1++;        } else {            N1[M1[s2]].inDegree++;        }        G1[M1[s1]][M1[s2]] = true;    }    for (int i = 0; i < n; i++) {  // 建图二        string s1, s2;        cin >> s1 >> s2;        if (M2.find(s1) == M2.end()) {            M2[s1] = n2;            N2[n2] = Node(s1, -1, 0, 1);            n2++;        } else {            N2[M2[s1]].outDegree++;        }        if (M2.find(s2) == M2.end()) {            M2[s2] = n2;            N2[n2] = Node(s2, -1, 1, 0);            n2++;        } else {            N2[M2[s2]].inDegree++;        }        G2[M2[s1]][M2[s2]] = true;    }}void cut() {  // 深搜前剪枝    for (int j, i = 0, k; i < n1; i++) {        int sameDegreeNum = 0;        for (j = 0; j < n2; j++) {            if (N1[i].inDegree == N2[j].inDegree && N1[i].outDegree == N2[j].outDegree) {                k = j;                sameDegreeNum++;            }        }        if (sameDegreeNum == 1) {  // 如果图一图二中有且仅有两点i、j且i与j的出度入度相同,那么ij必然为对应点            N1[i].match = k;            N2[k].match = i;        }    }}void DFS(int pos) {    if (pos == n1) {        succeed = true;        return;    }    if (N1[pos].match != -1) {  // 如果这个点已经匹配完成(cut函数剪枝)        DFS(pos + 1);        return;    }    for (int i = 0; i < n2; i++) {        if (N2[i].match == -1 && N1[pos].inDegree == N2[i].inDegree && N1[pos].outDegree == N2[i].outDegree) {            int j, k;            for (j = 0; j < n1; j++) {  // 如果点pos和点i是可以匹配的,但是在图一中有一个点j,pos连接到j,且j有在图二中的对应点,但是点i并不连接到j的对应点,那么这是不同构的                if (j != pos && G1[pos][j] && N1[j].match != -1 && !G2[i][N1[j].match]) break;            }            for (k = 0; k < n1; k++) {  // 如果点pos和点i是可以匹配的,但是在图一中有一个点j,j连接到pos,且j有在图二中的对应点,但是j的对应点并不连接到点i,那么这是不同构的                if (k != pos && G1[k][pos] && N1[k].match != -1 && !G2[N1[k].match][i]) break;            }            if (j == n1 && k == n1) {  // 以上两种不同构的情况都没有出现,继续                N1[pos].match = i;                N2[i].match = pos;                DFS(pos + 1);                if (succeed) return;                N1[pos].match = N2[i].match = -1;            }        }    }}int main() {    std::ios::sync_with_stdio(false);    bool firstTime = true;    while (1) {        cin >> n;        if (n == 0) break;        if (!firstTime) cout << endl;        firstTime = false;        makeG();        cut();        succeed = false;        DFS(0);        for (map<string, int>::iterator iter = M1.begin(); iter != M1.end(); iter++) {            cout << iter->first << "/" << N2[N1[iter->second].match].s << endl;        }    }    //getchar();    //getchar();        return 0;}                              


0 0
原创粉丝点击