poj1570

并查集的经典题目,有人说也可以用floyd。并操作时要记录子节点与父节点的兑换比例。

View Code
//zoj1705

//并查集,但是需要加入每个元素与祖先的价格比。 

#include <iostream>

#include <string>

using namespace std;



const    int        maxn = 200;



string    namelist[maxn];

int        listnum = 0, father[maxn][3];



int toint(string st)

{

    int        i, l = st.length(), x = 0;



    for (i = 0; i < l; i++)

        x = x * 10 + st[i] - '0';

    return x;

}



int    inlist(string st)

{

    int        i;



    for (i = 0; i < listnum; i++)

        if (st == namelist[i])

            return i;

    return -1;

}



void exchange(int *a, int *b)

{

    int        t;



    t = *a;

    *a = *b;

    *b = t;

}



void simplify(int *a, int *b)

{

    int        a1 = *a, b1 = *b;



    if (a1 < b1)

        exchange(&a1, &b1);

    while (b1 != 0)

    {

        a1 = a1 % b1;

        exchange(&a1, &b1);

    }

    *a = *a / a1;

    *b = *b / a1;

}



int findancestor(int pos, int *v, int *va)

{

    int        v1, v1a, a = father[pos][1], b = father[pos][2];

    

    if (father[pos][0] == pos)

    {

        *v = 1;

        *va = 1;

        return pos;

    }

    father[pos][0] = findancestor(father[pos][0], &v1, &v1a);

    father[pos][1] = a * v1;

    father[pos][2] = b * v1a;

    *v = father[pos][1];

    *va = father[pos][2];

    simplify(&father[pos][1], &father[pos][2]);

    return father[pos][0];

}



void assertion(string st)

{

    string    name1, name2, temp;

    int        value1, value2, pos, pos1, pos2, ancestor1, ancestor2, v1, v2, v1a, v2a;



    st.erase(0, 2);

    pos = st.find(" ");

    temp = st.substr(0, pos);

    st.erase(0, pos + 1);

    value2 = toint(temp);



    pos = st.find(" ");

    name1 = st.substr(0, pos);

    st.erase(0, pos + 3);

    

    pos = st.find(" ");

    temp = st.substr(0, pos);

    st.erase(0, pos + 1);

    value1 = toint(temp);



    name2 = st;



    pos1 = inlist(name1);

    pos2 = inlist(name2);

    simplify(&value1, &value2);

    if (pos1 != -1 && pos2 != -1)

    {

        ancestor1 = findancestor(pos1, &v1, &v1a);

        ancestor2 = findancestor(pos2, &v2, &v2a);

        father[ancestor1][0] = ancestor2;

        father[ancestor1][1] = v2 * v1a * value1;

        father[ancestor1][2] = v1 * v2a * value2;

        simplify(&father[ancestor1][1], &father[ancestor1][2]);

    }

    if (pos1 != -1 && pos2 == -1)

    {

        exchange(&value1, &value2);

        temp = name1;

        name1 = name2;

        name2 = temp;

        exchange(&pos1, &pos2);

    }

    if (pos2 == -1)

    {

        pos2 = listnum++;

        namelist[pos2] = name2;

        father[pos2][0] = pos2;

        father[pos2][1] = 1;

        father[pos2][2] = 1;

    }

    pos1 = listnum++;

    namelist[pos1] = name1;

    father[pos1][0] = pos2;

    father[pos1][1] = value1;

    father[pos1][2] = value2;

}



void query(string st)

{

    string    name1, name2;

    int        pos1, pos2, v1, v2, v1a, v2a, value1, value2, pos, ancestor1, ancestor2;

    

    st.erase(0, 2);

    pos = st.find(" ");

    name1 = st.substr(0, pos);

    st.erase(0, pos + 3);

    name2 = st;

    pos1 = inlist(name1);

    pos2 = inlist(name2);

    ancestor1 = findancestor(pos1, &v1, &v1a);

    ancestor2 = findancestor(pos2, &v2, &v2a);

    if (ancestor1 != ancestor2)

    {

        cout << "? " << name1 << " = ? " << name2 << endl;

        return;

    }

    value1 = v1 * v2a;

    value2 = v2 * v1a;

    simplify(&value1, &value2);

    cout << value2 << " " << name1 << " = " << value1 << " " << name2 << endl;

}



int main()

{

    string    st;



//    freopen("t.txt", "r", stdin);

//    freopen("y.txt", "w", stdout);

    getline(cin, st);

    while (st[0] != '.')

    {

        if (st[0] == '!')

            assertion(st);

        else

            query(st);

        getline(cin, st);

    }

    return 0;

}

 

你可能感兴趣的:(poj)