javascript
【floyd】【bitset】洛谷 P1841 [JSOI2007]重要的城市 题解
?
? ??bitset玄學(xué)完美優(yōu)化復(fù)雜度?
?
題目描述
參加jsoi冬令營的同學(xué)最近發(fā)現(xiàn),由于南航校內(nèi)修路截?cái)嗔嗽瓉硗ㄏ蛴?jì)算中心的路,導(dǎo)致去的路程比原先增加了近一公里。而食堂門前施工雖然也截?cái)嗔嗽瓉硗ㄏ蛴?jì)算中心的路,卻沒有使路程增加,因?yàn)榭梢哉业酵瑯娱L度的路作替代。其實(shí),問題的關(guān)鍵在于,路截?cái)嗟牡胤绞墙煌ㄒc(diǎn)。
?
同樣的情況也出現(xiàn)在城市間的交通中。某些城市如果出了問題,可能會(huì)引起其他很多城市的交通不便。另一些城市則影響不到別的城市的交通。jsoi冬令營的同學(xué)發(fā)現(xiàn)這是一個(gè)有趣的問題,于是決定研究這個(gè)問題。
?
他們認(rèn)為這樣的城市是重要的:如果一個(gè)城市c被破壞后,存在兩個(gè)不同的城市a和b(a, b均不等于c),a到b的最短距離增長了(或不通),則城市c是重要的。
?
jsoi冬令營的同學(xué)面對(duì)著一張教練組交給他們的城市間交通圖,他們希望能找出所有重要的城市。現(xiàn)在就請(qǐng)你來解決這個(gè)問題。
?
輸入輸出格式
輸入格式:
第一行兩個(gè)整數(shù)N,M,N為城市數(shù),M為道路數(shù)。
?
接下來M行,每行三個(gè)整數(shù),表示兩個(gè)城市之間的無向邊,以及之間的路的長度。
?
輸出格式:
一行,按遞增次序輸出若干的數(shù),表示重要的城市。
?
如果沒有點(diǎn)的話需要輸出一行
“No important cities.”
去掉引號(hào)。
?
輸入輸出樣例
輸入樣例#1:
4 4 1 2 1 2 3 1 4 1 2 4 3 2輸出樣例#1:
2說明
30%的數(shù)據(jù):$N\le 20$;
?
60%的數(shù)據(jù):$N\le 100$;
?
100%的數(shù)據(jù):$N\le 200,M\le \frac{N\times (N-1)}{2},0<c\le 10000$。$c$即路的長度。
?
保證不出現(xiàn)重邊和自環(huán)
?
感謝@趙昕鵬 和@qq2477259579 提供程序
?
題解:
? ??因?yàn)镕loyd是一種玄學(xué)DP思想,所以它的狀態(tài)更新來源有很多,在這個(gè)題里需要整理出它的階段性與轉(zhuǎn)移,看上去十分麻煩。而我們?nèi)绻袴loyd當(dāng)作最短路算法中的松弛,就是相當(dāng)于在把兩段最短路拼接在一起,擁有它們合在一起的性質(zhì)。
?
重要城市
? ??重要城市就是如果這個(gè)點(diǎn)被刪掉,那么最短路的長度就會(huì)改變。因此這個(gè)點(diǎn)一定在最短路上。而當(dāng)兩點(diǎn)間的最短路有多條時(shí),它們上的點(diǎn)不一定都是重要城市,經(jīng)過分析我們可以這樣理解:設(shè)$(u,v)$間最短路條數(shù)為$k$,重要城市為$p$,那么這$k$條最短路一定都經(jīng)過點(diǎn)$p$。用反例來說明,就是如果不是$k$條最短路都經(jīng)過點(diǎn)$p$,那么去掉點(diǎn)$p$,還有剩下的最短路可以走,則不合法。
?
? ??因此我們可以開一個(gè)三維數(shù)組$im[i][j][k]$表示k在$latex i,j$的幾條最短路上。而我們用floyd做最短路計(jì)數(shù)也比較方便,一旦$k$所在的最短路數(shù)量與$(i,j)$間的最短路數(shù)量相同,那么$k$就一定是一個(gè)重要城市,判斷條件為$im[i][j][k]==cnt[i][j]\Rightarrow k$是重要城市。
? ??在上圖中,1→8最短路計(jì)數(shù)為3,其中除了起點(diǎn)和終點(diǎn),被經(jīng)過了3次的點(diǎn)的點(diǎn)有2和7,因此它們是這條路徑上的重要城市。
?
? ??因?yàn)閒loyd的時(shí)間復(fù)雜度為$O(N^3)$,而每次更新還要循環(huán)一個(gè)$N$,因此總時(shí)間復(fù)雜度為$O(N^4)$。
?
bitset優(yōu)化
? ??我們?cè)谏厦嫣岬?#xff0c;狀態(tài)合并/更新需要額外枚舉一個(gè)$O(N)$,我們可不可以把這個(gè)$N$省掉,或者說優(yōu)化一點(diǎn)呢?
?
? ??這時(shí)可以考慮bitset,bitset可以使常數(shù)優(yōu)化32倍,這個(gè)題的$latex N$規(guī)模才200,優(yōu)化一個(gè)32就快把一個(gè)$N$變成一個(gè)$\log N$了,這個(gè)題的數(shù)據(jù)規(guī)模還是可以承受的。不過bitset存的是二進(jìn)制啊,可是上面提到的數(shù)組存的是計(jì)數(shù)啊。
?
? ??我們可以換一個(gè)方式想想,如果這兩個(gè)點(diǎn)之間已經(jīng)找到了4條最短路,其中有3條經(jīng)過點(diǎn)$p$,那此時(shí)$p$已經(jīng)不合法了,就直接把它置為0,以后盡管所有路徑都經(jīng)過$p$,它也不可能是關(guān)鍵城市。
?
? ??因此bitset中im[i][j][k]里面存的是,現(xiàn)有狀態(tài)下,k是不是i到j(luò)最短路上的關(guān)鍵城市。當(dāng)更新(松弛)最短路時(shí),關(guān)鍵城市是兩段最短路上的關(guān)鍵城市之并集;而更新最短路計(jì)數(shù),也就是找到了一條新的最短路時(shí),如上圖,就要取交集,因?yàn)橐粋€(gè)城市只有在兩點(diǎn)間任何一條最短路上都存在,才能作為這兩點(diǎn)間的關(guān)鍵城市。而交集并集在位運(yùn)算中就是and(&)和or(|),而點(diǎn)集有200,普通的位運(yùn)算完成不了,就讓bitset來做。
?
? ??在一開始初始化時(shí),把兩個(gè)連接在一起的點(diǎn)上的關(guān)鍵城市設(shè)為兩個(gè)端點(diǎn),在floyd“松弛”最短路時(shí),直接把兩段最短路的關(guān)鍵城市“拼起來”,就是新的最短路上的關(guān)鍵城市。最后判斷用$O(N^3)$遍歷,看一個(gè)點(diǎn)是否為某兩個(gè)點(diǎn)之間的關(guān)鍵城市,不過要注意不能與這兩個(gè)點(diǎn)重合,因?yàn)闉榱朔奖?#xff0c;一開始我們把起點(diǎn)和終點(diǎn)也定為關(guān)鍵城市(符合關(guān)鍵城市的一般定義)。
?
? ??因此這道題的總復(fù)雜度為$O(\frac{N^4}{32}+N^3)$
?
Code:
#include<cstdio> #include<cstring> #include<bitset> using std::bitset; bitset<210> im[210][210]; int f[210][210]; int is[210]; int main() {memset(f,0x3f,sizeof(f));int u,v,n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)f[i][i]=0;for(int i=1;i<=m;i++){scanf("%d%d",&u,&v);scanf("%d",&f[u][v]);f[v][u]=f[u][v];}for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){im[i][j][i]=1;//初始化設(shè)兩端為重要城市im[i][j][j]=1;}for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(f[i][k]+f[k][j]==f[i][j])im[i][j]&=(im[i][k]|im[k][j]);//當(dāng)更新計(jì)數(shù)時(shí)取交集else if(f[i][k]+f[k][j]<f[i][j])//當(dāng)更新最短路時(shí)直接賦值為兩段的并集{f[i][j]=f[i][k]+f[k][j];im[i][j]=im[i][k]|im[k][j];}for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)for(int k=1;k<=n;k++)if(k!=i&&k!=j)//注意特判if(im[i][j][k])is[k]=1;int flag=0;for(int i=1;i<=n;i++)if(is[i]){flag=1;printf("%d ",i);}if(!flag)//注意判斷無解puts("No important cities.");return 0; }
轉(zhuǎn)載于:https://www.cnblogs.com/wjyyy/p/lg1841.html
總結(jié)
以上是生活随笔為你收集整理的【floyd】【bitset】洛谷 P1841 [JSOI2007]重要的城市 题解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。