HDU - 4725 The Shortest Path in Nya Graph(最短路+思维)
題目鏈接:點(diǎn)擊查看
題目大意:給定n個(gè)點(diǎn),在一般的基礎(chǔ)上給每個(gè)點(diǎn)一個(gè)維度,也就是多了一個(gè)參數(shù)表示所在的層次,現(xiàn)在已知:
在以上兩個(gè)條件的基礎(chǔ)上,求點(diǎn)1到點(diǎn)n的最小值。
題目分析:這個(gè)題的題意很好懂,就是圖很難建,一開(kāi)始我沒(méi)有想到什么好的方法,就是先保存了每一層的點(diǎn)數(shù),然后兩兩枚
舉,令相鄰兩層的所有點(diǎn)都建上權(quán)值為C的一條邊,確實(shí)很莽,也確實(shí)果不其然的MLE了,然后靜下心來(lái)想了一下,每?jī)蓚€(gè)點(diǎn)都
建上邊的話,題目中點(diǎn)最多有1e5這么多,即使不算上那m條邊的話,最壞情況下也是到了1e10的數(shù)量級(jí),不爆內(nèi)存才怪呢。。
想了很久無(wú)果之后,去網(wǎng)上搜了搜題解,感覺(jué)大牛們的做法真的很棒,也值得我去向他們學(xué)習(xí),我就把他們的想法用自己的語(yǔ)表
達(dá)一下吧:
假設(shè)每一層也是一個(gè)點(diǎn),這樣的話每一次的最壞情況就是每一層只有一個(gè)點(diǎn),一共有n個(gè)點(diǎn)和n個(gè)層,這樣的話最壞情況下會(huì)出現(xiàn)
2*n個(gè)點(diǎn),然后每個(gè)點(diǎn)都屬于一層,所以每個(gè)點(diǎn)都要和其對(duì)應(yīng)的層建邊,然后每個(gè)點(diǎn)在和相鄰的兩層建邊,也就是3*n條邊,最后
加上m條已經(jīng)建好的邊,那么最多只會(huì)有3*n+m條邊,最壞的情況也才4e5,比1e10小了不止一點(diǎn)半點(diǎn),這樣的話建完圖就可以
直接套spfa或Dijkstra了。
講一講為什么可以這樣想吧:
因?yàn)槊總€(gè)點(diǎn)都屬于一個(gè)層,所以我們可以表示該層到該點(diǎn)的距離為0,然后因?yàn)槊恳粚佣伎梢砸詸?quán)值C到達(dá)相鄰的兩層,所以令該
點(diǎn)再與該層的相鄰兩層所表示的點(diǎn)來(lái)建邊,權(quán)值為C即可。我們可以舉個(gè)很簡(jiǎn)單的例子:
例如,現(xiàn)在有三個(gè)點(diǎn),每?jī)蓪又g花費(fèi)的權(quán)值為C,那么我們需要六個(gè)點(diǎn)來(lái)維護(hù)這個(gè)圖,設(shè)點(diǎn)1,點(diǎn)2和點(diǎn)3表示的是點(diǎn)的本身,
點(diǎn)4,點(diǎn)5和點(diǎn)6表示的是第一層,第二層和第三層(先不管每一層是否有點(diǎn),反正層數(shù)再多也不會(huì)比點(diǎn)的個(gè)數(shù)還多)。然后我們
假設(shè)點(diǎn)1和點(diǎn)2位于第1層,點(diǎn)3位于第2層,這樣我們建邊的時(shí)候,就有4->1(0),4->2(0),5->3(0),1->5(C),2->5(C),3->4(C)
3->6(C)這里采用u->v(w)的形式,來(lái)表示每一條邊。怎么樣,看到這里應(yīng)該有一種豁然開(kāi)朗的感覺(jué)了吧?是的,如果我們現(xiàn)在要
求點(diǎn)1到點(diǎn)3之間的距離,因?yàn)槲覜](méi)有給出任何連接的邊,所以只能跨層得到連通路,也就是1->5(C)->3(0),最短路也就是C了。
再說(shuō)一下為什么要建單向邊吧,接著上面舉得例子,加入是雙向邊,那么關(guān)于點(diǎn)1和點(diǎn)2的邊為:4->1(0),1->4(0),4->2(0),
2->4(0)。假如接下來(lái)我們給出一條已知的邊來(lái)連接點(diǎn)1和點(diǎn)2,設(shè)1->2(w),那么我們現(xiàn)在來(lái)求一下點(diǎn)1到點(diǎn)2的距離,如果滿足題
意的話求出來(lái)的答案肯定是w,但是按照雙向邊來(lái)求的話會(huì)出現(xiàn)以下情況:1->4(0)->2(0),結(jié)果就是點(diǎn)1到點(diǎn)2的最短距離為0,
這個(gè)結(jié)果肯定與正確答案相悖,而將其替換成單向邊的話,就可以得出正確結(jié)果了。
直接上代碼了:
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<stack> #include<queue> #include<map> #include<sstream> #include<cmath> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=2e5+100;//記得將N提前預(yù)設(shè)為兩倍大小,因?yàn)槲覀冃枰o每一層預(yù)設(shè)出位置,一開(kāi)始沒(méi)注意這里,RE了一發(fā)struct Node {int w,to;Node(int TO,int W){w=W;to=TO;} };vector<Node>node[N];int d[N];bool vis[N];void spfa() {memset(vis,false,sizeof(vis));memset(d,inf,sizeof(d));d[1]=0;vis[1]=true;queue<int>q;q.push(1);while(!q.empty()){int tem=q.front();q.pop();vis[tem]=false;for(int i=0;i<node[tem].size();i++){Node temp=node[tem][i];if(d[temp.to]>d[tem]+temp.w){d[temp.to]=d[tem]+temp.w;if(!vis[temp.to]){q.push(temp.to);vis[temp.to]=true;}}}} }int main() { // freopen("input.txt","r",stdin);int w;cin>>w;int kase=0;while(w--){int n,m,c;scanf("%d%d%d",&n,&m,&c);for(int i=1;i<=2*n;i++)node[i].clear();for(int i=1;i<=n;i++){int a;scanf("%d",&a);node[a+n].push_back(Node(i,0));//建立從層到點(diǎn)的邊if(a>1){node[i].push_back(Node(a+n-1,c));//建立從點(diǎn)到上一層的邊}if(a<n){node[i].push_back(Node(a+n+1,c));//建立從點(diǎn)到下一層的邊}}for(int i=1;i<=m;i++){int a,b,c;scanf("%d%d%d",&a,&b,&c);node[a].push_back(Node(b,c));node[b].push_back(Node(a,c));}spfa();//建好邊之后就可以直接跑模板了printf("Case #%d: ",++kase);if(d[n]==inf)cout<<-1<<endl;elsecout<<d[n]<<endl;}return 0; }?
總結(jié)
以上是生活随笔為你收集整理的HDU - 4725 The Shortest Path in Nya Graph(最短路+思维)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: LightOJ - 1074 Exten
- 下一篇: POJ - 2299 Ultra-Qui