Luogu1186 瑪麗卡 題解

2022-08-10 17:12:16 字數 1959 閱讀 9054

翻了翻題解,貌似沒有用vector進行存圖的,既然這樣那本蒟蒻就貼乙個vector的題解。

題目思路比較簡單,先跑一遍正常的最短路,然後列舉在這條最短路上的每一條邊,將其長度翻倍,再跑一遍最短路,輸出新的最短路減去舊的最短路之後的最大值。

本題關鍵就是如何記錄原先的最短路:

在dijkstra更新距離d陣列時額外記錄前驅節點,即記錄d[i]的上一步d[j],本操作可以使用結構體實現。

**塊:

//列舉與x點相連的每一條邊。

for(register int i=0;id[x].val+v[x][i].val)

}

由於d陣列存的是1號點到所有點的最短路,而我們需要的有效路徑只是從1到n的最短路,所以如果將路徑記錄完畢後將路徑提取出來,後面將路徑翻倍會相對更容易實現,我們可以利用遞迴從n點倒著退回來,將有效路徑單獨儲存出來。

inline void return(int xx)

//最後儲存出來的路徑即為

//1->road_recorder[1]->road_recorder[2]->……->n

vector操作核心:將路徑長度翻倍

使用vector存圖時改變路徑長一般用列舉方式實現。若將x點與y點的路徑長翻倍,我們需要列舉與x相連的所有邊,直至找到y點,將此邊改變。由於是雙向圖,我們需要再重複此操作更改y與x相連的邊。由於列舉導致本步時間複雜度並不確定。

由於我們還要再改其他的邊,所以我們改完當前邊並記錄結果之後還需將其還原,所以我們在修改時直接記錄下此邊在vector中的位置,\(o(1)\)還原。

//last為起點,road_recorder[i]為目標點

for(register int j=0;j路徑的還原v[last][change1].val>>=1;

v[road_recorder[i]][change2].val>>=1;

最後貼完整**
#include#include#include#define inf 2000000000

using namespace std;

priority_queue,vector>,greater> >q;

struct nodeadd;

vectorv[1001];

struct noded[1001];

bool f[1001];

inline void add(int x,int y,int z)

int m,n,x,y,z,h,ans,change1,change2,r1,r2,dd[1001],road_recorder[1001],last=1;

inline void return(int xx)

int main()

memset(d,0x7f,sizeof(d));

d[1].val=d[1].from=0;

q.push(make_pair(0,1));

/* 首先跑一邊dij,算出原始最短路 ↓*/

while(!q.empty())}}

return(n);//提取記錄的路徑

for(register int i=1;i<=h;i++)}}

if(dd[n]>ans)ans=dd[n];//比較答案

v[last][change1].val=r1;//路徑還原

v[road_recorder[i]][change2].val=r2;//路徑還原

last=road_recorder[i];//本次的目標點會成為下次的起點

//last初值為1

}printf("%d",ans);

}

如上文所說,由於列舉導致時間複雜度並不確定,資料類似菊花圖的話可能會被卡的慢一些,但是保證肯定不會tle

資料範圍n<=1000,最慢的點304ms,真的算很快了。平均複雜度貌似\(o(n^2logn)\)?

題解 P1186 瑪麗卡

這個題意實在是太模糊了,我也是聽了大佬的解釋才明白的。我可以再次翻譯一遍題意qaq 找出在一條邊斷掉的情況下的單源最短路徑,並輸出最壞的情況 去邊不同會影響最短路 完了?完了。所以思路就出來了 一一去掉所有邊,分別去求最短路。仔細想想 時間複雜度 dijkstra o n 2 m 如果是dalao寫...

洛谷 1186 瑪麗卡

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

洛谷 P1186 瑪麗卡

這道題題目真的想吐槽一下.是在機房同學的解釋下才看懂的。就是讓你求在可以刪一條邊的情況下,並且刪後保證可以到達終點時,求刪了後的最大的最短路徑。70分暴力思路 列舉刪邊,然後跑一下最短路即可,思路很簡單,下面給出70分 include using namespace std vector e 101...