CodeVS1021 瑪麗卡 最短路 線段樹

2021-08-20 19:31:20 字數 3518 閱讀 8493

題目鏈結

宣告:感謝fzw(kryj)的創意和熱心講解

麥克找了個新女朋友,瑪麗卡對他非常惱火並伺機報復。

因為她和他們不住在同乙個城市,因此她開始準備她的長途旅行。

在這個國家中每兩個城市之間最多只有一條路相通,並且我們知道從乙個城市到另乙個城市路上所需花費的時間。

麥克在車中無意中聽到有一條路正在維修,並且那兒正堵車,但沒聽清楚到底是哪一條路。無論哪一條路正在維修,從瑪麗卡所在的城市都能到達麥克所在的城市。

瑪麗卡將只從不堵車的路上通過,並且她將按最短路線行車。麥克希望知道在最糟糕的情況下瑪麗卡到達他所在的城市需要多長時間,這樣他就能保證他的女朋友離開該城市足夠遠。

編寫程式,幫助麥克找出瑪麗卡按最短路線通過不堵車道路到達他所在城市所需的最長時間(用分鐘表示)。

城市數n

≤1000

n

≤1000

麥克在1,瑪麗卡在n

幾乎所有網上能找到的題解都是nm的,好鬱悶。。

具體地說,他們都是在當前最短路上列舉刪邊,重新跑spfa或者dijkstra

這種做法的時間複雜度很好分析。原最短路上的邊數為o(n)級別,每一次最短路至少要遍歷所有邊,所以是o(nm)。當m≈

n2m ≈n

2o(n

2)o (n

2)

,spfa演算法則更慢。因此網上n次spfa的**顯然應該o(

n3) o(n

3)

t到不知**去了

但是codevs的資料好像根本沒卡?沒關係我有一資料生成器請諸位享用

#include

int n=1000;

intm=n*(n-1)/2;

int main()

}

實測黃學長的**跑了32秒。。。

我們考慮刪掉原最短路上的一條邊之後的圖

刪邊後,有些點到起點s的最短路ds不變,我們設這個點集為l;有些點到終點t的最短路dt不變,我們設這個點集為r

每個點至少在l和r的乙個中,因為假設點p不在任何乙個,說明p到s和t的最短路都經過被刪的邊。假設被刪的邊是(u->v),邊長為w,那麼路徑u-v-p比路徑u-p(不經過v,以下同理)短,v-u-p比v-p短,這樣的話,d(u-p)>d(v-p)+w且d(v-p)>d(u-p)+w,顯然是矛盾的

因而新的最短路一定是先在l中走,經過一條邊,進入r集合,最後到達t。

我們可以列舉這條中間的邊,就能找到所有「可能的」新最短路長度。

但是怎麼才能知道某個邊帶來的路徑會不會受堵車的邊的影響呢?

從s到t的路徑一定可以從原最短路上的某個點脫離,再從某個點返回到原最短路

我們使得保證s-u和v-t長度不變(即保持l,r集合的性質)的情況下,盡量地早脫離,晚返回,這樣就能使得脫離點和返回點之間的所有邊都無法對其產生影響。實現前一點我們可以通過在原最短路上按順序從每乙個點開始,只走ds

u+w=

dsv dsu

+w=d

sv

的邊看可以到達哪些點,把這些點的最早脫離位置都儲存起來。後一點也同樣,只是反過來。

在列舉一條(u,v,w)的邊時,如果可以從l點脫離到達u,再從v點出發在r點返回,那麼刪去l到r之間的任意一條邊,都仍存在一條長度為ds

u+w+

dtv dsu

+w+d

tv

的路徑可以從s到達t,最後我們要求的是刪去每個邊的情況中,新最短路的最長值,相當於乙個序列,支援區間內所有數和另乙個數取min,最後要查詢整個序列的最大值,線段樹可以解決這個問題

求原圖最短路並標記上面的點和邊,並按序編號——o(

m+nl

ogn)o(

m+nl

ogn)

求每乙個點i想在l集合中,最早的脫離位置lili

(上一條的編號),dfs實現,每個點最多被遞迴進入一次,從這個點出發的邊也只能被走一次——o(m)o

(m

)求每個點想在r集合中的最晚返回位置riri

,同上列舉每條邊,給刪去原最短路上[l

i+1,

ri] [li

+1,r

i]

中邊的情況增加一種可能路徑——o(mlogn)

線段樹整體求最大值——o(logn)

很長,但是我嚴謹我自豪

#include

#include

#include

#include

using

namespace

std;

#define maxn 1004

#define inf 2147483647

int n,m,c;

struct edge

edge(){}

}e[maxn*maxn];

int ind[maxn];

int newedge=1;

void addedge(int l,int v,int u)

int read()

return d;

}struct node

};bool

operator

<(node a,node b)

int ds[maxn],dt[maxn];

int dep[maxn];

int f[maxn];

bool vzt[maxn];

priority_queueprq;

void dijkstra(int s,int *d)

int u=x.id;

for(int j=ind[u];j;j=e[j].next)}}

}bool dtag[maxn];

bool btag[maxn*maxn];

int a[maxn];

int l[maxn],r[maxn];

void dfs(int u,int *a,int *d)

}namespace segtree

void pushdown(int t)

}void

set(int ql,int qr,int v,int t=1,int l=1,int r=c)

pushdown(t);

int mid=(l+r)>>1;

if(mid>=ql) set(ql,qr,v,t*2,l,mid);

if(mid+1

<=qr) set(ql,qr,v,t*2+1,mid+1,r);

}int getmax(int t=1,int l=1,int r=c)

}int main()

c=dep[n];

for(int i=0;i<=c;i++)

memset(vzt,0,sizeof(vzt));

for(int i=c;i>=0;i--)

for(int i=2;i<=newedge;i++)

printf("%d",segtree::getmax());

}

Code VS 1021 瑪麗卡題解

spfa algorithm 題目傳送門 麥克找了個新女朋友,瑪麗卡對他非常惱火並伺機報復。因為她和他們不住在同乙個城市,因此她開始準備她的長途旅行。在這個國家中每兩個城市之間最多只有一條路相通,並且我們知道從乙個城市到另乙個城市路上所需花費的時間。麥克在車中無意中聽到有一條路正在維修,並且那兒正堵...

Codevs 1021 瑪麗卡 洛谷 P1186

時間限制 2 s 空間限制 128000 kb 題目等級 大師 master 麥克找了個新女朋友,瑪麗卡對他非常惱火並伺機報復。因為她和他們不住在同乙個城市,因此她開始準備她的長途旅行。在這個國家中每兩個城市之間最多只有一條路相通,並且我們知道從乙個城市到另乙個城市路上所需花費的時間。麥克在車中無意...

codevs 瑪麗卡(最短路路徑記錄)

時間限制 2 s 空間限制 128000 kb 題目等級 大師 master 題解 題目描述 description 麥克找了個新女朋友,瑪麗卡對他非常惱火並伺機報復。因為她和他們不住在同乙個城市,因此她開始準備她的長途旅行。在這個國家中每兩個城市之間最多只有一條路相通,並且我們知道從乙個城市到另乙...