【演算法】最大生成樹+lca(倍增)
【題解】兩點間選擇一條路徑最小值最大的路徑,這條路徑一定在最大生成樹上,因為最大生成樹就是從邊權最大的邊開始加的。
先求原圖的最大生成樹(森林),重新構圖,然後用乙個超級根連向每棵樹的根。
對於每個詢問,在樹上跑z=lca(x,y),答案就是x到z,z到y路上的最小值。
這個最小值可以在lca(倍增)的過程中順便維護(ms陣列),和祖先(倍增)陣列的維護方式類似。
ms[e[x].to][0]=e[i].w;
ms[x][i]=min(ms[x][i-1],ms[f[x][i-1]][i-1]);
求ans的時候,x,y每次向上推進都求一次ans=min(ans,...),具體可以看程式。
【注意】(只是提醒自己t_t)
1.每次要更新x,y的位置前先求ans。
2.無向邊建兩條,陣列要開大,而且後面求生成樹的時候要用建邊總數而不是原邊總數m!!!
3.超級根用0容易出錯,用比maxn大的數字即可。
4.重新構圖的新邊表和舊邊表各種變數注意區分
#include#includeview code#include
using
namespace
std;
const
int inf=0x3f3f3f3f,maxn=10010
;bool
ok[maxn];
struct cyceo[150010],e[150010
];int cnt,tot,head[maxn],heads[maxn],fa[maxn],f[maxn][16],ms[maxn][16
],vis[maxn],deep[maxn],n,m,q;
void insert(int u,int v,int
w)void ins(int u,int v,int
w)int getfa(int
x)bool
cmp(cyc a,cyc b)
void dfs(intx)}
}int lca(int x,int
y)int
main()
sort(eo+1,eo+cnt+1
,cmp);
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=cnt;i++)
}for(int i=1;i<=n;i++)
if(!ok[getfa(i)])ok[fa[i]]=1,ins(10010
,fa[i],inf);
//for(int i=1;i<=tot;i++)printf("%d %d %d\n",e[i].from,e[i].to,e[i].w);
dfs(10010
); scanf("%d
",&q);
for(int i=1;i<=q;i++)
return0;
}
NOIP 2013 提高組 貨車運輸
a 國有 n 座城市,編號從 1 到 n,城市之間有 m 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。現在有 q 輛貨車在運輸貨物,司機們想知道每輛車在不超過車輛限重的情況下,最多能運多重的貨物。第一行有兩個用乙個空格隔開的整數 n,m,表示 a 國有 n 座城市和 m 條道路。接下來 m ...
NOIP2013提高組 貨車運輸
noip2013 提高組 day1 試題。a 國有 n 座城市,編號從 1 到 n,城市之間有 m 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。現在有 q 輛貨車在運輸貨物,司機們想知道每輛車在不超過車輛限重的情況下,最多能運多重的貨物。第一行有兩個用乙個空格隔開的整數 n m,表示 a 國...
題解 NOIP2013 提高組 貨車運輸
使用演算法 堆優化 prim lca 大樣例題目鏈結 共有 n 個點,有 m 條邊來連線這些點,每條邊有權值。有 q 條類似於 u v 詢問,求一條從 u 到 v 的路徑使得路徑上的最小權值最大,求這個最大值。若不存在從 u 到 v 的路徑,則輸出 1 先求該圖的最大生成樹,因為需要使得該路徑上的最...