題意: 給出一些關係用aX <= bY表示, 最後查詢aX 和 bY的關係,是>=,==,<=,仍是不能肯定,仍是出現了矛盾。ios
解法:對每個關係其實均可以建一條X->Y的邊,邊權爲b/a,表示X <= b/a*Y,輸入完後,跑一遍floyd,對每一對點A,B跑出A<=xB的x的最小值。ide
由於若是真的存b/a的話,可能會損失很大的精度,可是好像這樣也能過。爲了更加保險,咱們能夠取個對數,log(b/a) = log(b)-log(a),那麼乘法就變成了加法,更好計算,也更加準確。spa
最後就是判斷了,設最後查詢的是k1,k2兩個點,比率爲ka,kbcode
1.==: 若是mp[k1][k2] == -mp[k2][k1], 便是倒數關係(對數是負數關係),且mp[k1][k2] = log(kb/ka),那麼就相等。blog
2.<=: 若是mp[k1][k2] <= log(kb/ka), 如今k1已經小於等於mp[k1][k2]了,那麼確定是小於等於log(kb/ka)的。ci
3.>=: -mp[k2][k1] >= log(kb/ka) string
4.INCONSISTENT: 若是某個mp[i][i]爲負,說明有矛盾。it
5.其餘狀況io
代碼:event
#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; }