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;
}

 

posted @ 2013-03-26 15:58  金海峰  阅读(143)  评论(0编辑  收藏  举报