description
給乙個n個點m條邊的連通無向圖,滿足每條邊最多屬於乙個環,有q組詢問,每次詢問兩點之間的最短路徑。input
輸入的第一行包含三個整數,分別表示n和m和q 下接m行,每行三個整數v,u,w表示一條無向邊v-u,長度為woutput最後q行,每行兩個整數v,u表示一組詢問
輸出q行,每行乙個整數表示詢問的答案sample input
9 10 2sample output hint1 2 1
1 4 1
3 4 1
2 3 1
3 7 1
7 8 2
7 9 2
1 5 3
1 6 4
5 6 1
1 95 7
對於100%的資料,n<=10000,q<=10000題解
又做個裸題爽一爽….這次要把圓方樹建出來
圓點到圓點的邊權即為原邊權
圓點到方點的邊權即為這個圓點到方點的父親的最短路長度
考慮如何計算答案
先對要求的兩個點求lca
如果lca是圓點,直接輸出答案
如果是方點,我們發現最後路徑是在乙個環上
設求的是(x,y)的答案,我們把(x,y)移到(u,v),保證u,v均是圓點且是lca的孩子節點
再暴力計算u,v的環上最短路即可
#include
#include
#include
#include
#include
using namespace std;
struct nodea[210000],e[210000];int len1,last1[210000],len2,last2[210000];
void ins_a(int
x,int
y,int c)
void ins_b(int
x,int
y,int c,int d)
int low[210000],dfn[210000],sta[210000],r[210000],id,cnt,tp1;
int belong[210000],d[210000],gg[210000],hh[210000],po[210000],go[210000],root,tp2;
void link()
hh[cnt]=sum;
ins_b(cnt,r[1],0,0);ins_b(r[1],cnt,0,0);
for(int i=2;i<=r[0];i++)
/* puts("checker:::::");
for(int i=1;i<=r[0];i++)printf("%d
%d\n",r[i],d[i]);
printf("%d\n",sum);*/
}bool v[210000];
void tarjan(int
x,int fa)
while(i!=y);
link();}}
else
}}int bin[25],fa[210000][25],s[210000][25],num[210000],dep[210000];
void pre_tree_node(int
x) }
}int tmp;
int lca(int
x,int
y)int up(int
x,int p)
int n,m,q;
int main()
memset(v,false,sizeof(v));
memset(dfn,-1,sizeof(dfn));cnt=n;
for(int i=1;i<=n;i++)if(dfn[i]==-1)
// for(int i=1;i<=len2;i++)printf("checker: %d
%d%d
%d\n",e[i].x,e[i].y,e[i].c,e[i].d);
while(q--)
}return
0;}
BZOJ2125 最短路 圓方樹
思路 關於靜態仙人掌的問題,建立出圓方樹比較好求解。求出來之後處理每個圓點方點的情況,原來的是樹邊直接處理,環邊的話方點連向環上每個圓點一條邊,權值為每個節點到環的父親節點的最短距離。然後倍增預處理,查詢的時候,如果lc a lca 是圓點直接輸出,否則兩個點是環上的點,處理他們在環上的最短距離即可...
BZOJ2125最短路 初識圓方樹
sto sto sto yyb orz orz orz bzoj2125 非許可權 不知道圓方樹應該歸在資料結構還是圖論,先放在這裡,圓方樹,對於狹義圓方樹,可以解決一類仙人掌的問題。對於仙人掌的定義,通俗來講就是對於乙個無向圖每一條邊有且僅僅被乙個環所包含 最後看起來就像是乙個乙個環圈圈,最終ju...
BZOJ2125 最短路 圓方樹 倍增LCA
最短路 做法 本題需要用到圓方樹來處理仙人掌。題目中所給的圖稱作仙人掌圖,即每條邊至多在乙個環上的圖。對於這種圖,我們一般把它轉化成樹後,將樹上的某些演算法修改後來解決仙人掌上的問題。常用的一種轉化方式就是圓方樹。在圓方樹中,乙個圓點表示原仙人掌中就有的點,而乙個方點表示乙個點雙連通分量 環 並且乙...