Fork me on GitHub

UVALive 4431 Fruit Weights --floyd,差分约束?

题意: 给出一些关系用aX <= bY表示, 最后查询aX 和 bY的关系,是>=,==,<=,还是不能确定,还是出现了矛盾。

解法:对每一个关系其实都可以建一条X->Y的边,边权为b/a,表示X <= b/a*Y,输入完后,跑一遍floyd,对每一对点A,B跑出A<=xB的x的最小值。

因为如果真的存b/a的话,可能会损失很大的精度,但是好像这样也能过。为了更加保险,我们可以取个对数,log(b/a) = log(b)-log(a),那么乘法就变成了加法,更好计算,也更加准确。

最后就是判断了,设最后查询的是k1,k2两个点,比率为ka,kb

1.==: 如果mp[k1][k2] == -mp[k2][k1], 即是倒数关系(对数是负数关系),且mp[k1][k2] = log(kb/ka),那么就相等。

2.<=: 如果mp[k1][k2] <= log(kb/ka), 现在k1已经小于等于mp[k1][k2]了,那么肯定是小于等于log(kb/ka)的。

3.>=: -mp[k2][k1] >= log(kb/ka) 

4.INCONSISTENT: 如果某个mp[i][i]为负,说明有矛盾。

5.其他情况

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <string>
#include <map>
#define Mod 1000000007
#define eps 1e-8
using namespace std;

double mp[205][205];
map<string,int> ms;

int sgn(double x) {
    if(x > eps) return 1;
    if(x < -eps) return -1;
    return 0;
}

int main()
{
    int n,i,j,a,b,tot,u,v,k;
    string S;
    while(scanf("%d",&n)!=EOF && n)
    {
        tot = 0;
        ms.clear();
        for(i=1;i<=2*n;i++) {
            for(j=1;j<=2*n;j++)
                mp[i][j] = Mod;
            mp[i][i] = 0.0;
        }
        for(i=1;i<=n;i++) {
            scanf("%d",&a);
            cin>>S;
            if(!ms[S]) ms[S] = ++tot;
            u = ms[S];
            scanf("%d",&b);
            cin>>S;
            if(!ms[S]) ms[S] = ++tot;
            v = ms[S];
            mp[u][v] = min(mp[u][v],log((double)b/(double)a));
        }
        for(k=1;k<=tot;k++) {
            for(i=1;i<=tot;i++) {
                for(j=1;j<=tot;j++)
                    mp[i][j] = min(mp[i][j],mp[i][k]+mp[k][j]);
            }
        }
        string S1,S2;
        scanf("%d",&a);
        cin>>S1;
        int k1 = ms[S1];
        scanf("%d",&b);
        cin>>S2;
        int k2 = ms[S2];
        double rate = log((double)b/(double)a);
        if(ms[S1] == 0 || ms[S2] == 0) { puts("UNAVAILABLE"); continue; }
        for(i=1;i<=tot;i++) if(sgn(mp[i][i]) < 0) { puts("INCONSISTENT"); break; }
        if(i != tot+1) continue;
        if(sgn(mp[k1][k2]+mp[k2][k1]) == 0 && sgn(mp[k1][k2]-rate) == 0) puts("==");
        else if(sgn(mp[k1][k2]-rate) <= 0) puts("<=");
        else if(sgn(-mp[k2][k1]-rate) >= 0) puts(">=");
        else puts("UNAVAILABLE");
    }
    return 0;
}
View Code

 

posted @ 2015-01-20 19:01 whatbeg 阅读(...) 评论(...) 编辑 收藏