HDU 3666(差分約束)

2022-05-24 15:39:08 字數 3262 閱讀 1721

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 

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 }

順便嘗試了一下**中提到的貪心初始流寫法,發現這麼寫效率雖然沒什麼差別,但是可以省去vis陣列,還是有效果的!(不用預流處理且不加vis陣列的話會超時。)

1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 

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

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 }

view code

差分約束 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...