UVALive 4080 最短路樹

2021-08-15 15:55:42 字數 1559 閱讀 9367

給n個點,m條邊,如果兩個點之間沒有邊,則預設為l。問所有點兩兩之間最短路之和是多少。然後刪除一條邊,問刪除某一條邊後最大是多少。

這道題第一問可以很簡單用floyd演算法求解。但是第二問如果使用floyd演算法,就會存在超時的問題。貪心上也沒有比較好的策略,因此考慮使用最短路演算法暴力列舉。但是由於暴力列舉可能超時,因此引入最短路樹的概念。最短路樹就是乙個點到其他所有點的最短路所形成的樹。

在使用最短路演算法鬆弛的時候記錄一下前置節點,就可以輕而易舉的得到最短路樹。然後對於暴力求解的過程,如果我們刪除的邊不在最短路上,那麼最短路將不會重新計算。這樣整體的複雜度就會變成o(n^2*m*log(n)),這個時間複雜度剛好足夠。

需要注意的是,這道題存在重邊的情況,對於重邊,如果刪除一條邊,則會採用其他邊頂替。這一點在處理的時候需要特別注意。

#include 

#define ll long long

#define up(i,l,h) for(int i=l;i#define down(i,h,l) for(int i=h-1;i>=l;i--)

#define w(t) while(t)

#define mem(a,b) memset(a,b,sizeof(a))

#define inf 0x3f3f3f3f

#define maxn 210

#define cout(x) cout<#define int ll

using

namespace

std;

int dis[maxn][maxn];

int n,m,l;

struct node

node(int u,int d):u(u),d(d) {}

};bool vis[maxn];

int d[maxn],p[maxn];

int dijkstra(int u)

return sum;

}int ans[maxn];

bool tree[maxn][maxn];

bool intree[maxn][4050];

struct edge

};vector

edges;

int sec[maxn][maxn];

main()

}up(i,0,m) else

edges.push_back(edge(a-1,b-1,s));

}mem(intree,false);

up(i,0,n)

up(j,0,m) }}

int temp1=0;

up(i,0,n) temp1+=ans[i];

int temp2=temp1;

up(i,0,m)

dis[edges[i].u][edges[i].v]=dis[edges[i].v][edges[i].u]=distemp;

// cout(te***);

temp2=max(temp2,te***);

}printf("%lld %lld\n",temp1,temp2);

}}

最短路樹 BZOJ 3694 最短路

題目傳送門 許可權題警告 顯然可以發現,將1到i路徑上的最後一條路切斷後,需要重新找到一條從i的子樹出發的最短路徑重新回到最短路樹上去.因此考慮一條邊什麼時候會被計算在答案中.設一條邊u v權值為val,只會可能對u,v到 lca u,v 之間的點產生影響.記錄源點1到節點i的距離為dep i 那麼...

最短路徑樹

問題描述 所謂最短路徑樹,就是從s出發,沿著樹上的邊走到任意點i,那麼經過的這些邊的權值和就是s到i的最短路徑。dijkstra演算法或spfa演算法不僅可計算從起點s到各點的最短路徑長度,同時也可得到以s為根的最短路徑樹。方法是在進行鬆弛操作時,如果d i c d j 時,除了更新d j 之外,還...

最短路徑,最短路徑樹和最小生成樹

首先介紹這三個概念,很多人都聽過最短路徑了,但是最短路徑樹卻很少聽過,關於最短路徑樹的介紹也不太多。而最短路徑樹和最小生成樹更是完全不同的兩個概念。最短路徑就是從乙個指定的頂點出發,計算從該頂點出發到其他所有頂點的最短路徑。通常用dijkstra演算法,floyd演算法求解。最短路徑樹spt sho...