用什麼
首先,他需要把n個點連線起來且只用n-1條邊,還要使總邊權和最小,那麼很明顯是最小生成樹啦。
習慣用克魯斯卡爾演算法。
怎麼做
不過此處有乙個條件限制就是要加一條李牌的邊,就是只選n-2條王牌的邊。
那麼很顯然的是這n-2條邊是在最小生成樹上的邊。
所以先建立最小生成樹。
那麼我們只要列舉所有李牌的邊,替換一條李牌的邊或建立一條新邊,例如從x到y費用z,因為要使其是一顆樹,如果建立了一條新邊就需要在x,y到x,y的公共祖先上刪去一條王牌的邊才可以,且費用要盡量的大。
那麼我們在倍增求lca是也順便用倍增的方法把最大費用的一條邊及其的序號找出來即可。
注意
有一種情況是王牌的邊建完最小生成樹之後只有n-2條邊,所以需要進行特判。
#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
#define rep(i,a) for(i=first[a];i;i=next[i])
using namespace std;
const int maxn=800007;
int i,j,k,l,t,n,m,w,e,num,x,y,z;
int fa[maxn],ans,first[maxn],next[maxn],last[maxn],tot,chang[maxn],an[maxn];
int ans1,ans2,ab[maxn],b[maxn],c[maxn],f[maxn][20],g[maxn][20],aa,q[maxn][20],xu[maxn];
int ans3[maxn],ans4,bb,deep[maxn];
struct nodea[maxn];
bool cmp(node x,node y)
int gf(int
x)void add(int
x,int
y,int z,int
q)void dfs(int
x,inty)}
int lca(int
x,int
y)int main()
sort(a+1,a+1+num,cmp);
fo(i,1,l)
ans=0x7fffffff;
fo(i,1,num)
if(m==n-1)break;
}if(m==n-2)
dfs(1,0);
fo(j,1,19)fo(i,1,n)
fo(i,1,l)
printf("%d\n",ans1);
}
架設電話線 題解
原題來自 usaco 2008 jan.silver 在郊區有 n 座通訊基站,p 條雙向電纜,第 i 條電纜連線基站 a i 和 b i 特別地,1 號基站是通訊公司的總站,n 號基站位於一座農場中。現在,農場主希望對通訊線路進行公升級,其中公升級第 i 條電纜需要花費 l i 公司正在舉行優惠活...
架設電話線 二分答案 SPFA
description farmer john打算將 線引到自己的農場,但電信公司並不打算為他提供免費服務。於是,fj必須為此向電信公司支付一定的費用。fj的農場周圍分布著n 1 n 1,000 根按1 n順次編號的廢棄的 線 杆,任意兩根 線桿間都沒有 線相連。一共p 1 p 10,000 對 線...
二分答案 spfa 架設電話線
架設 線 phoneline 題目描述 farmer john打算將 線引到自己的農場,但電信公司並不打算為他提供免費服務。於是,fj必須為此向電信公司支付一定的費用。fj的農場周圍分布著n 1 n 1,000 根按1.n順次編號的廢棄的 線桿,任意兩根 線桿間都沒有 線相連。一共p 1 p 10,...