To Heart 題解 SCOI2009迷路

2022-09-18 10:33:26 字數 3790 閱讀 5064

題解第二部分

**** 原題來自:scoi 2009**

windy 在有向圖中迷路了. 該有向圖有 n

nn個節點,windy 從節點 0

00 出發,他必須恰好在t

tt時刻到達節點 n−1

n-1n−

1。現在給出該有向圖,你能告訴 windy 總共有多少種不同的路徑嗎?

注意:windy 不能在某個節點逗留,且通過某有向邊的時間嚴格為給定的時間。

第一行包含兩個整數n

nn,ttt;

接下來有 n

nn行,每行乙個長度為n

nn的字串。第i

ii行第j

jj列為 0表示從節點i

ii到節點j

jj沒有邊,為1

11到9

99表示從節點i

ii節點j

jj需要耗費的時間。

包含乙個整數,可能的路徑數,這個數可能很大,只需輸出這個數除以2009

2009

2009

的餘數。

2 2

1100

1
5 30

12045

07105

47805

12024

12345

852
2 <= n <= 10 ; 1 <= t <= 1000000000 ;0<=邊權<=9;

第一反應:咦?這不是圖論嗎???

默默的看了眼t的範圍,死了心

dp!! dp一定可以!!!

默默的看了眼t的範圍,又死了心

那麼怎麼做呢?

首先,我們把這道題想簡單一點,如果題目中的每一條邊都沒有邊權,只用1或0來表示兩個點之間是否存在邊,並且用鄰接矩陣來存這張圖,那麼我們又可以得到些什麼呢?

我們以下面這張圖為例

以鄰接矩陣來表示這個矩陣:

0 1 1

1 0 1

1 0 0 //矩陣1

其中,ai

j表示i到j之間是否有連線;

2 0 1

1 1 1

0 1 1 //矩陣2

你又發現了什麼呢?

好的,如果還沒發現,我們再來將矩陣1三次方一下:

1 2 2

2 1 2

2 0 1 //矩陣3

什麼,你還沒發現嗎???

那麼讓我來告訴你吧!!!

仔細觀察矩陣1,我們可以把aij看成通過一條邊,由i到達j的情況總數

矩陣2、矩陣3也是如此;

不信?我們舉個栗子:

從點1到點2,且通過一條邊的情況不存在,記為0;

從點1到點2,且通過兩條邊的情況共兩種(1->2->1 and 1->3->1),記為2;

從點1到點2,且通過三條邊的情況僅有一種(1->2->3->1),記為1;

再回頭看看矩陣吧!!!是不是完全滿足這個條件呢???

所以我們就可以得出結論啦:

在矩陣ax中,ax

ij表示由i到j經過x條邊的情況總數

所以這就可以運用快速冪啦!!!

仔細算一下時間複雜度,o(n*logn),穩穩滴!!!

那麼,這道題就可以很快打出來啦——嗎?

顯然是不可以的。

可能你已經發現了,我們所有的推論都建立在邊權為1的情況上,可是這道題目呢?

接下來有 n

nn行,每行乙個長度為n

nn的字串。第i

ii行第j

jj列為 0表示從節點i

ii到節點j

jj沒有邊,為1

11到9

99表示從節點i

ii到節點j

jj需要耗費的時間。

呀呀呀,這道題目的邊權不只是1呀!

!(⊙ o ⊙)!

怎麼辦呢?

雖然我們發現不能直接使用我們的結論,但是最大邊權是9!n也不超過10!都不算大!

那我們就可以採用一種叫做拆點的方法:把乙個點拆成10個點。

並且,我們發現即使如此拆點,n也不會超過100,妥妥的可以呀!

但怎麼拆點呢?

我們先來試一下拆乙個邊權不超過2的圖吧!

可得矩陣

0 2

2 1

將其拆點:

把1.1看成節點1;

把1.2看成節點2;

把2.1看成節點3;

把2.2看成節點4;

可得到新矩陣 :

0 1 0 0

0 0 1 0

0 0 1 1

1 0 0 0

將其平方:

0 0 1 0

0 0 1 1

1 0 1 1

0 1 0 0

再驗算一下,

原來有點1到點2並用經過2邊權的方案總數有一種(1->2,邊權為2);

現在來說,點1變為點1,點2變為點3,經過2邊權的方案總數依舊是2(1->2->3,邊權均為1);

那麼則說明我們的拆點是正確的。

那麼怎麼做呢?

我們再對非零點進行分類,原先就有的1看成藍色,後面通過自連得到的1看成紅色:

那麼下面的**就可以進行拆點操作:

int

cheak

(int i,

int j)

void

chaidian()

for(

int j=

1;j<=n;j++)}

}}

那麼既然我們通過拆點操作將所有點之間的邊權都變成了1,那麼我們就可以用剛才得到的定理啦!!!

#include

using

namespace std;

int n,t;

const

long

long mod=

2009

;struct matrix

}a;matrix yunsuan

(matrix x, matrix y)}}

return now;

}matrix power

(matrix a,

int b)

while

(b)return now;

}int

cheak

(int i,

int j)

intmain()

for(

int j=

1;j<=n;j++)}

} a=

power

(a,t)

;printf

("%d\n"

,a.ma[1]

[10*n-9])

;}

To Heart 題解 戳西瓜

請不要吝嗇你的點讚!有 n 個西瓜,編號為0 到 n 1,每個西瓜上都標有乙個數字,這些數字存在陣列 nums 中。現在要求你戳破所有的西瓜。每當你戳破乙個西瓜 i 時,你可以獲得 nums left nums i nums right 個硬幣。這裡的 left 和 right 代表和 i 相鄰的兩...

To Heart 題解 內需消費

題目鏈結 首先,我們先假設這道題不需要修改物價,那麼我們如何找到最好的情況呢?差分。如下數列 1 4 3 5 2很容易觀察出,在第乙個商店到第二個商店中,我們最多可以賺3元,在第乙個商店進貨,第二個商店賣出。但是在第二個商店到第三個商店的途中,我們不能賺錢。因為第二個商店的 比第三個商店的 的 大,...

To Heart 題解 內需消費

題目鏈結 首先,我們先假設這道題不需要修改物價,那麼我們如何找到最好的情況呢?差分。如下數列 1 4 3 5 2很容易觀察出,在第乙個商店到第二個商店中,我們最多可以賺3元,在第乙個商店進貨,第二個商店賣出。但是在第二個商店到第三個商店的途中,我們不能賺錢。因為第二個商店的 比第三個商店的 的 大,...