有乙個完全圖,邊有邊權。
對於每個 \(i\),求一棵生成樹,使得( \(\sum_^n\)
\(j\) 到 \(i\) 的路徑上邊權最小值) 最小。
\(n\leq 2000,w\leq ^9\)
記最小的邊權 \(w\),這條邊的乙個端點為 \(s\)。
那麼 \(i\) 號點對應的生成樹就是從 \(i\) 到 \(s\) 的一條路徑,然後經過邊權最小的邊,再連向所有點。
可以發現 \(i\) 到 \(s\) 的路徑上除了最後一條邊之外的邊權是遞減的。而且每條邊的邊權 \(<\) 後面所有邊(除了最後一條邊)的邊權和。所以深度會 \(\leq o(\log w)\)。
直接從每個點開始跑最短路就可以做到 \(o(n^2\log w)\) 。
從 \(s\) 開始向每個點跑最短路就可以在 \(o(n^2)\) 內解決這道題了。
#include#include#include#include#include#include#include#include#include//using namespace std;
using std::min;
using std::max;
using std::swap;
using std::sort;
using std::reverse;
using std::random_shuffle;
using std::lower_bound;
using std::upper_bound;
using std::unique;
using std::vector;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef std::pairpii;
typedef std::pairpll;
void open(const char *s)
void open2(const char *s)
int rd()dowhile((c=getchar())>='0'&&c<='9');return b?-s:s;}
void put(int x)static int c[20];int t=0;while(x)while(t)putchar(c[t--]+'0');}
int upmin(int &a,int b)return 0;}
const int n=2010;
int a[n][n];
int b[n];
ll s[n];
int n;
int mi[n];
int main()
b[t]=1;
s[t]=0;
for(int i=1;i<=n;i++)
if(i!=t)
s[i]=min(a[t][i]-w,2*mi[i]-2*w);
for(int i=1;ifor(int i=1;i<=n;i++)
printf("%lld\n",s[i]+(ll)(n-1)*w);
return 0;
}
xsy2304 哈 最短路
題目大意 有乙個 n 個點,m 條有向邊的圖,有 q 組詢問。每次詢問 從 a 到 b 經過不超過 c 條邊,且依次經過的邊邊權遞增,問最短路為多少,無解輸出 1。資料範圍 n 150 m 5000 q 1000 我場上並沒有去想正解,打了個spfa居然獲得 90pts 好成績。首先對於經過不超過 ...
XSY1162 鬼計之夜 最短路
給你乙個 n 個點 m條邊的有向圖,有 k 個關鍵點。求一條最短的從乙個關鍵點到另乙個關鍵點的路徑。n,m,k 100000跑k 2 次最短路顯然會tle 考慮兩個不同的數有什麼可以利用的性質。其中會有至少乙個二進位制為不同!所以可以列舉所有二進位制位,從 0 的那邊向 1的那邊跑最短路,再從 1 ...
XSY2679 修牆 最短路
有乙個 n 1 m 1 的網格,每條邊都有乙個邊權。有一些格仔是城市。你要用乙個環圈住所有城市,要求環上所有邊的邊權和最小。重合的邊邊權算多次。保證左上角 1 1 一定有乙個城市。n,m 400 觀察到左上角一定有乙個城市。首先求出每個城市左上角到 0 0 的最短路,那麼這個圈肯定不會經過最短路。如...