2015-01-08 22:48:00
思路:巧妙的建圖...
由: l <= cij * ai / bj <= u,要轉化成加減的話全體套上log...
化為:log(l) <= log(cij) + log(ai) - log(bj) <= log(u)
--> (1) log(ai) <= log(bj) + log(u) - log(cij)
--> (2) log(bj) <= log(ai) + log(cij) - log(l)
對點進行編號,1~n為a1~n,n+1~n+m為b1~m,那麼上述(1)(2)約束就化為:
(1) s(i) <= s(n + j) + log(u) - log(cij)
(2) s(n + j) <= s(i) + log(cij) - log(l)
然後判斷是否有負環即可,用dfs版spfa不會超時~
(至於佇列版spfa超時,有些人把判圈的範圍變小(比如弄成sqrt(總數)),這種寫法正確性尚待考究...有用正確性來換時間的嫌疑 -。-)
關於寫法,有個細節:對每乙個點進行spfa,用vis陣列判斷是否已經判斷過這個點(防超時),一旦遍歷到某個仍在棧中的點說明有負圈。
(具體可參考2023年國家集訓隊姜碧野的**。)
1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include順便嘗試了一下**中提到的貪心初始流寫法,發現這麼寫效率雖然沒什麼差別,但是可以省去vis陣列,還是有效果的!(不用預流處理且不加vis陣列的話會超時。)8 #include 9 #include 10 #include 11 #include 12
using
namespace
std;
13#define lp (p << 1)
14#define rp (p << 1|1)
15#define getmid(l,r) (l + (r - l) / 2)
16#define mp(a,b) make_pair(a,b)
17 typedef long
long
ll;18 typedef unsigned long
long
ull;
19 typedef pairpii;
20const
int inf = (1
<< 30) - 1;21
const
int maxn = 1000;22
23int
n,m,l,u,g;
24int
first[maxn],ecnt;
25int
inq[maxn],cnt[maxn],vis[maxn];
26double
dis[maxn];
2728
struct
edgee[maxn * maxn * 2
];32
33 inline void add_edge(int u,int v,double
c)39
40bool spfa(int
p)49
}50 inq[p] = 0;51
return
true;52
}5354bool
solve()62}
63return
true;64
}6566int
main()79}
80for(int i = n + m; i >= 1; --i)
81 add_edge(0,i,0
);82
if(solve()) printf("
yes\n");
83else printf("
no\n");
84}85return0;
86 }
1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #includeview code8 #include 9 #include 10 #include 11 #include 12
using
namespace
std;
13#define lp (p << 1)
14#define rp (p << 1|1)
15#define getmid(l,r) (l + (r - l) / 2)
16#define mp(a,b) make_pair(a,b)
17 typedef long
long
ll;18 typedef unsigned long
long
ull;
19 typedef pairpii;
20const
int inf = (1
<< 30) - 1;21
const
int maxn = 1000;22
23int
n,m,l,u,g;
24int
first[maxn],ecnt;
25int
inq[maxn],cnt[maxn];
26double
dis[maxn];
2728
struct
edgee[maxn * maxn * 2
];32
33 inline void add_edge(int u,int v,double
c)39
40bool spfa(int
p)49
}50 inq[p] = 0;51
return
true;52
}5354bool spfa_init(int
p)62}63
return
false;64
}
6566
bool
solve()
7677
intmain()90}
91for(int i = n + m; i >= 1; --i)
92 add_edge(0,i,0
);93
if(solve()) printf("
yes\n");
94else printf("
no\n");
95}96return0;
97 }
差分約束 hdu 3666
xij ai l bj 0 xij ai u bj 0 兩邊取對數來去除ai,bj前面的係數 有 logbj logai logxij logu logai log bj logl logxij 化成標準差分約束,建圖,spfa,注意乙個竅門,當入隊總數大於2 n m 時就可以輸出no 因為 乙個點...
HDU3666 差分約束
思路 根據題意可得,l a i g i j b j u,看到不等式,馬上想到差分約束 將上式移項得l g i j a i b j u g i j 再取對數log l g i j log a i log b j log u g i j 最後構造 的不等式,用spfa跑最短路,若存在負環,說明無解,輸出...
hdu 3666差分約束
題目描述 給你乙個n m的矩陣,給你兩個數l和u l u 問你是否存在這樣的n m個數字 計作a1 an,b1 bm 使矩陣中任意元素xij,滿足 l xij ai bj u 輸出yes or no。解題報告 轉換成 xij ai u bj 0 和 l bj xij ai 0 差分約束中的xi xj...