生活随笔
收集整理的這篇文章主要介紹了
Codevs 1519 过路费(Mst+Lca)
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1519 過(guò)路費(fèi)
時(shí)間限制: 1 s
空間限制: 256000 KB
題目等級(jí) : 大師 Master
題目描述 Description
在某個(gè)遙遠(yuǎn)的國(guó)家里,有 n個(gè)城市。編號(hào)為 1,2,3,…,n。這個(gè)國(guó)家的政府修建了m 條雙向道路,每條道路連接著兩個(gè)城市。政府規(guī)定從城市 S 到城市T需要收取的過(guò)路費(fèi)為所經(jīng)過(guò)城市之間道路長(zhǎng)度的最大值。如:A到B長(zhǎng)度為 2,B到C 長(zhǎng)度為3,那么開(kāi)車(chē)從 A經(jīng)過(guò) B到C 需要上交的過(guò)路費(fèi)為 3。
佳佳是個(gè)做生意的人,需要經(jīng)常開(kāi)車(chē)從任意一個(gè)城市到另外一個(gè)城市,因此他需要頻繁地上交過(guò)路費(fèi),由于忙于做生意,所以他無(wú)時(shí)間來(lái)尋找交過(guò)路費(fèi)最低的行駛路線(xiàn)。然而, 當(dāng)他交的過(guò)路費(fèi)越多他的心情就變得越糟糕。 作為秘書(shū)的你,需要每次根據(jù)老板的起止城市,提供給他從開(kāi)始城市到達(dá)目的城市,最少需要上交多少過(guò)路費(fèi)。
輸入描述 Input Description
第一行是兩個(gè)整數(shù) n 和m,分別表示城市的個(gè)數(shù)以及道路的條數(shù)。
接下來(lái) m 行,每行包含三個(gè)整數(shù) a,b,w(1≤a,b≤n,0≤w≤10^9),表示a與b之間有一條長(zhǎng)度為 w的道路。
接著有一行為一個(gè)整數(shù) q,表示佳佳發(fā)出的詢(xún)問(wèn)個(gè)數(shù)。
再接下來(lái) q行,每一行包含兩個(gè)整數(shù) S,T(1≤S,T≤n,S≠T), 表示開(kāi)始城市S 和目的城市T。
輸出描述 Output Description
輸出共q行,每行一個(gè)整數(shù),分別表示每個(gè)詢(xún)問(wèn)需要上交的最少過(guò)路費(fèi)用。輸入數(shù)據(jù)保證所有的城市都是連通的。
樣例輸入 Sample Input
4 5
1 2 10
1 3 20
1 4 100
2 4 30
3 4 10
2
1 4
4 1
樣例輸出 Sample Output
20
20
數(shù)據(jù)范圍及提示 Data Size & Hint
對(duì)于 30%的數(shù)據(jù),滿(mǎn)足 1≤ n≤1000,1≤m≤10000,1≤q≤100;
對(duì)于 50%的數(shù)據(jù),滿(mǎn)足 1≤ n≤10000,1≤m≤10000,1≤q≤10000;
對(duì)于 100%的數(shù)據(jù),滿(mǎn)足 1≤ n≤10000,1≤m≤100000,1≤q≤10000;
分類(lèi)標(biāo)簽 Tags
分治 最小生成樹(shù) 圖論
/*
Slf(spfa優(yōu)化).
50棄療了.
跑最小生成樹(shù)后Slf.
有一個(gè)鏈的測(cè)試點(diǎn)卡不過(guò)去.
(不搞mst的話(huà)還是能卡過(guò)去的).
論常數(shù)的重要性orz.
*/
using namespace std;
int head[MAXN],n,
m,k,cut,father[MAXN],tot,dis[MAXN],
q[MAXN];
struct edge{
int v,
next;
int x;}e[MAXN
*2];
struct data{
int x,
y,z;}
s[MAXN
*2];
bool b[MAXN];
int read()
{
int x=
0,f=
1;char ch=getchar();
while(ch<
'0'||ch>
'9') ch=getchar();
while(ch>=
'0'&&ch<=
'9')
x=
x*10+ch-
48,ch=getchar();
return x;
}
int ffind(
int x)
{
return x!=father[
x]?father[
x]=ffind(father[
x]):
x;
}
void add(
int u,
int v,
int z)
{e[++cut].v=v;e[cut].
x=z;e[cut].
next=head[u];head[u]=cut;
}
bool cmp(const data &
x,const data &
y)
{
return x.z<
y.z;
}
int spfa(
int s,
int t)
{
int u,v;
int head1=
1,tail=
1;
for(
int i=
1;i<=n;i++) dis[i]=
1e1
0,b[i]=false;
q[head1]=
s;dis[
s]=
0;
while(head1<=tail){u=
q[head1++];b[u]=false;
if(head1>n+
1) head1=
1;
for(
int i=head[u];i;i=e[i].
next){v=e[i].v;
if(dis[v]>max(dis[u],e[i].
x)){dis[v]=max(dis[u],e[i].
x);
if(!b[v]){b[v]=true;
if(dis[v]>dis[
q[head1]]){
if(--head1<
0) head1=n;
q[head1]=v;}
else {
q[++tail]=v;
if(tail>n+
1) tail=
1;}}}}}
return dis[t];
}
int main()
{
int x,
y,z;n=
read(),
m=
read();
for(
int i=
1;i<=n;i++) father[i]=i;
for(
int i=
1;i<=
m;i++)
x=
read(),
y=
read(),z=
read(),
s[i].
x=
x,
s[i].
y=
y,
s[i].z=z;
sort(
s+
1,
s+
m+
1,cmp);
for(
int i=
1;i<=
m;i++){
x=ffind(
s[i].
x),
y=ffind(
s[i].
y);
if(
x!=
y){tot++;father[
x]=
y;add(
s[i].
x,
s[i].
y,
s[i].z);add(
s[i].
y,
s[i].
x,
s[i].z);}
if(tot==n-
1)
break;}k=
read();
while(k--){
x=
read(),
y=
read();
printf(
"%d\n",spfa(
x,
y));}
return 0;
} /*
mst定理:最小生成樹(shù)里的最長(zhǎng)邊最短.
然后lca維護(hù)兩點(diǎn)距離.
還有不要漏下某種情況.
*/
using namespace std;
int head[MAXN],n,
m,k,cut,father[MAXN],tot,st,fa[MAXN][D+
5],deep[MAXN],dis[MAXN][D+
5];
struct edge{
int v,
next;
int x;}e[MAXN
*2];
struct data{
int x,
y,z;}
s[MAXN
*2];
int read()
{
int x=
0,f=
1;char ch=getchar();
while(ch<
'0'||ch>
'9'){
if(ch==
'-') f=-
1;ch=getchar();}
while(ch>=
'0'&&ch<=
'9')
x=
x*10+ch-
48,ch=getchar();
return x;
}
int ffind(
int x)
{
return x!=father[
x]?father[
x]=ffind(father[
x]):
x;
}
void add(
int u,
int v,
int z)
{e[++cut].v=v;e[cut].
x=z;e[cut].
next=head[u];head[u]=cut;
}
bool cmp(const data &
x,const data &
y)
{
return x.z<
y.z;
}
void dfs(
int u,
int f,
int d)
{deep[u]=d+
1;
for(
int i=head[u];i;i=e[i].
next){
int v=e[i].v;
if(f!=v){fa[v][
0]=u;dis[v][
0]=e[i].
x;dfs(v,u,d+
1);}}
return ;
}
void get_father()
{
for(
int j=
1;j<=D;j++)
for(
int i=
1;i<=n;i++)fa[i][j]=fa[fa[i][j-
1]][j-
1],dis[i][j]=max(dis[fa[i][j-
1]][j-
1],dis[i][j-
1]);
return ;
}
int get_same(
int u,
int v)
{
for(
int i=
0;i<=D;i++){
if((
1<<i)&v){tot=max(tot,dis[u][i]);u=fa[u][i];}}
return u;
}
int lca(
int u,
int v)
{tot=
0;
if(deep[v]>deep[u]) swap(u,v);u=get_same(u,deep[u]-deep[v]);
if(u==v)
return tot;
for(
int i=D;i>=
0;i--){
if(fa[u][i]!=fa[v][i]){tot=max(tot,max(dis[u][i],dis[v][i]));u=fa[u][i];v=fa[v][i];}}tot=max(tot,max(dis[u][
0],dis[v][
0]));
return tot;
}
int main()
{
int x,
y,z;n=
read(),
m=
read();
for(
int i=
1;i<=n;i++) father[i]=i;
for(
int i=
1;i<=
m;i++)
x=
read(),
y=
read(),z=
read(),
s[i].
x=
x,
s[i].
y=
y,
s[i].z=z;
sort(
s+
1,
s+
m+
1,cmp);
for(
int i=
1;i<=
m;i++){
x=ffind(
s[i].
x),
y=ffind(
s[i].
y);
if(
x!=
y){tot++;father[
x]=
y;add(
s[i].
x,
s[i].
y,
s[i].z);add(
s[i].
y,
s[i].
x,
s[i].z);}
if(tot==n-
1)
break;}dfs(
1,
1,
0);get_father();k=
read();
while(k--){
x=
read(),
y=
read();
printf(
"%d\n",lca(
x,
y));}
return 0;
}
轉(zhuǎn)載于:https://www.cnblogs.com/nancheng58/p/10068172.html
總結(jié)
以上是生活随笔為你收集整理的Codevs 1519 过路费(Mst+Lca)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。