bzoj3669 NOI2014 魔法森林

2021-07-09 11:25:14 字數 1398 閱讀 8189

給定n個點m條邊的無向圖,每條邊有兩個權值a與b。求一條1到n的路徑使得路徑經過邊的最大a與最大b的和最小。無法到達輸出-1。

n<=50000,m<=100000。

我們嘗試列舉路徑的最大a值,那麼我們只需按照a排序按順序插入,維護1到n的b最大值即可。

用並查集維護連通性。當加入j到k這條邊時如果形成環,則刪除環上的最大值。

我們用動態樹來進行維護。

為了實現更易,將每條邊看做乙個點,例如第i條邊兩個端點是j與k,那麼將i+n與j、k相連,權值放在代表邊的點上。

#include

#include

#include

#include

#define fo(i,a,b) for(i=a;i<=b;i++)

using

namespace

std;

const

int maxn=50000+10;

stack

sta;

struct dong;

dong e[maxn*2];

int tree[maxn*3][2],key[maxn*3],father[maxn*3],num[maxn*3],pp[maxn*3],fa[maxn];

int i,j,k,l,t,n,m,ans;

bool bz[maxn*3];

int max(int a,int b)

int pd(int x)

void update(int x)

void rotate(int x)

void clear(int x)

}void romove(int x,int y)

while (!sta.empty())

}void splay(int x,int y)

}void access(int x)

}void makeroot(int x)

void link(int x,int y)

void cut(int x,int y)

int getfa(int x)

bool cmp(dong a,dong b)

else

//printf("%d\n",i);

continue;}}

else fa[getfa(k)]=getfa(j);

key[i+n]=e[i].b;

num[i+n]=i+n;

link(i+n,j);

link(i+n,k);

if (getfa(1)==getfa(n))

//printf("%d\n",i);

}if (ans==10000000) ans=-1;

printf("%d\n",ans);

}

bzoj 3669 Noi2014 魔法森林

description 為了得到書法大家的真傳,小e同學下定決心去拜訪住在魔法森林中的隱士。魔法森林可以被看成乙個包含個n節點m條邊的無向圖,節點標號為1.n,邊標號為1.m。初始時小e同學在1號節點,隱士則住在號節點n。小e需要通過這一片魔法森林,才能夠拜訪到隱士。魔法森林中居住了一些妖怪。每當有...

bzoj 3669 NOI2014 魔法森林

為了得到書法大家的真傳,小e同學下定決心去拜訪住在魔法森林中的隱士。魔法森林可以被看成乙個包含個n節點m條邊的無向圖,節點標號為1.n,邊標號為1.m。初始時小e同學在號節點1,隱士則住在號節點n。小e需要通過這一片魔法森林,才能夠拜訪到隱士。魔法森林中居住了一些妖怪。每當有人經過一條邊的時候,這條...

BZOJ3669 NOI2014魔法森林

按a從小到大排序,然後按b建圖。每次只需要找1 n中最大的b加當前的a計算答案即可。這裡還有乙個小操作就是化邊為點,把一條邊的邊權看做乙個點的點權然後多連兩條邊。by 大奕哥 1 include2 using namespace std 3const int n 4e5 10 4 int fa n ...