Kruskal+LCA【p2245】 星际导航
Description
sideman做好了回到Gliese 星球的硬件準備,但是sideman的導航系統還沒有完全設計好。為了方便起見,我們可以認為宇宙是一張有\(N\) 個頂點和\(M\) 條邊的帶權無向圖,頂點表示各個星系,兩個星系之間有邊就表示兩個星系之間可以直航,而邊權則是航行的危險程度。
sideman 現在想把危險程度降到最小,具體地來說,就是對于若干個詢問(A, B),sideman 想知道從頂點\(A\) 航行到頂點\(B\) 所經過的最危險的邊的危險程度值最小可能是多少。作為sideman 的同學,你們要幫助sideman 返回家園,兼享受安全美妙的宇宙航行。所以這個任務就交給你了。
Input
第一行包含兩個正整數\(N\) 和\(M\),表示點數和邊數。
之后 \(M\) 行,每行三個整數\(A\),$B \(和\)L\(,表示頂點\)A$ 和\(B\) 之間有一條邊長為\(L\) 的邊。頂點從\(1\) 開始標號。
下面一行包含一個正整數 \(Q\),表示詢問的數目。
之后 \(Q\) 行,每行兩個整數\(A\) 和\(B\),表示詢問\(A\) 和\(B\) 之間最危險的邊危險程度的可能最小值。
Output
對于每個詢問, 在單獨的一行內輸出結果。如果兩個頂點之間不可達, 輸出\(impossible\)。
woc這不是\(Noip\ 2013\)貨車運輸.
切掉!
顯然,我們可以發現.想要讓一些頂點聯通,并且讓最危險的邊的危險程度值最小。
優先想到了\(Kruskal\).
首先\(Kruckal\)建樹。
如何求兩點間的距離?帶權\(LCA\)即可.
如果兩點不在一顆樹,要輸出\(impossible\)!!
剛開始輸出錯了
注意如果寫兩個結構體的話,對其中一個\(Sort\)(建樹)的話,不要結構體中重載\(<\)
代碼
#include<cstdio> #include<algorithm> #include<cctype> #define R register #define N 100008 using namespace std; inline void in(int &x) {int f=1;x=0;char s=getchar();while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}while(isdigit(s)){x=x*10+s-'0';s=getchar();}x*=f; } int n,m,head[N],tot,q; int fa[N],cnt,depth[N],f[N][21],gw[N][21]; struct cod{int u,v,w;}edge[300010],tree[300010]; inline bool ccp(const cod&a,const cod&b) {return a.w<b.w; } int find(int x){return fa[x]==x ? x : fa[x]=find(fa[x]);} inline void add(int x,int y,int z) {edge[++tot].u=head[x];edge[tot].v=y;edge[tot].w=z;head[x]=tot; } inline void kruskal() {for(R int i=1;i<=n;i++)fa[i]=i;sort(tree+1,tree+m+1,ccp);for(R int i=1;i<=m;i++){int u=tree[i].u,v=tree[i].v,w=tree[i].w;int fu=find(u),fv=find(v);if(fu==fv)continue;add(u,v,w);add(v,u,w);fa[fu]=fv;cnt++;if(cnt==n-1)break;}return ; } void dfs(int u,int fat,int dis) {depth[u]=depth[fat]+1;gw[u][0]=dis;f[u][0]=fat;for(R int i=1;(1<<i)<=depth[u];i++){f[u][i]=f[f[u][i-1]][i-1];gw[u][i]=max(gw[u][i-1],gw[f[u][i-1]][i-1]);}for(R int i=head[u];i;i=edge[i].u){if(edge[i].v==fat)continue;dfs(edge[i].v,u,edge[i].w);} } inline int lca(int x,int y) {int res=-214748364;if(depth[x]>depth[y])swap(x,y);for(R int i=20;i>=0;i--)if(depth[x]+(1<<i)<=depth[y])res=max(res,gw[y][i]),y=f[y][i];if(x==y)return res;for(R int i=20;i>=0;i--){if(f[x][i]==f[y][i])continue;res=max(res,gw[x][i]);res=max(res,gw[y][i]);x=f[x][i],y=f[y][i];}return max(max(res,gw[x][0]),gw[y][0]); } int main() {in(n),in(m);for(R int i=1;i<=m;i++)in(tree[i].u),in(tree[i].v),in(tree[i].w);kruskal();dfs(1,0,0);in(q);for(R int i=1,x,y;i<=q;i++){in(x),in(y);R int fx=find(x),fy=find(y);if(fx!=fy)puts("impossible");else printf("%d\n",lca(x,y));} }轉載于:https://www.cnblogs.com/-guz/p/9769005.html
總結
以上是生活随笔為你收集整理的Kruskal+LCA【p2245】 星际导航的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么判断u盘质量 如何评估U盘品质
- 下一篇: POJ--2104 K-th Numbe