傳送門
題目大意是:
有一些點,分為幾層,然後層與層之間可花費代價c到達,還有一些特殊邊,使得某個點和某個點之間花費某代價可以到達,求從1到n的最小代價。
一開始的想法是,既然層與層之間可以到達,那麼對於第i層和第i+1層,把第i層的所有點與第i+1層的所有點連邊,權值為c,特殊的邊該怎麼連怎麼連,然後跑最短路。
然後我看了一下資料範圍——n, m (0 <= n, m <= 105) 笑不出來
好吧,那讓我們考慮一下如何優化。
我們知道,同一層內的點是可以相互到達的且無花費。也就是說,如果我想去到第i層,我到達第i層的某個點後就相當於我到了這一層中所有的點。
那麼對於每一層,我可以建乙個入點和乙個出點(或者說就建乙個點也行,反正連進和連出的邊的性質是一樣的)。層與層之間就有建的點相連(代價就為c),層內的點全部連向建的點(代價為0)。
連變數:2*n+m 時間o(e loge)能過
注意:1.建的虛擬點的編號一定不要和原來的點重複了。2.圖中的點不再是n個,而應該建成3n個
#include #include最短路(hdu4725)(建點巧妙)#include
#include
#define n 100003
#define m 100003
using
namespace
std;
intread()
while(s>='
0'&&s<='9')
return x*f;
}const
int inf=0x3f3f3f3f
;struct
qnode
bool
operator
};struct
edge
};vector
e[n*2+m];
bool vis[n*3
];int dist[n*3];
void dij(int n,int start)//
點的編號從1開始
}}}
void add(int u,int v,int
w)int
main()
for(int i=1;i<=m;++i)
for(int i=1;i<=n;++i)
dij(
3*n,1
); printf(
"case #%d: %d\n
",k,(dist[n]==inf?-1
:dist[n]));
}} /*
*/
HDU 5521 巧妙地最短路
題意 n個點,m塊,塊的意思就是說,在塊中的點任意兩點的距離都是t,問分別從1點和n點走到某個點,這個點的花費就是二者較大的,問這n個點花費最小是多少,並按字典序列印序號 思路 這題頭疼的就是不知道怎麼建圖,暴力建圖會超記憶體,有乙個巧妙的方法是 將這個塊中的點全部連到乙個點上,每條邊花費t 2,這...
HDU 5521 Meeting 拆點 最短路
題目鏈結 給m個由圖中結點組成的點集,點集中的點兩兩連通且距離為相等的ti。現有兩人分別從1和n點處同時出發嗎,問能否相遇以及相遇的最短時間。很容易想到直接分別以點1和點n為起始點求最短路,再遍歷各個點即可求得最短相遇時間。然而建圖上卻有問題 這個題中的邊是以點集的形式給出,極端情況下可能會出現有1...
HDU 5521 Meeting 拆點 最短路
題目鏈結 給m個由圖中結點組成的點集,點集中的點兩兩連通且距離為相等的ti。現有兩人分別從1和n點處同時出發嗎,問能否相遇以及相遇的最短時間。很容易想到直接分別以點1和點n為起始點求最短路,再遍歷各個點即可求得最短相遇時間。然而建圖上卻有問題 這個題中的邊是以點集的形式給出,極端情況下可能會出現有1...