NOI2014 魔法森林

2021-07-25 22:11:02 字數 2130 閱讀 6660

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

魔法森林中居住了一些妖怪。每當有人經過一條邊的時候,這條邊上的妖怪就會對其發起攻擊。 幸運的是, 在 1 號節點住著兩種守護精靈: a 型守護精靈與b 型守護精靈。小 e 可以借助它們的力量,達到自己的目的。

只要小 e 帶上足夠多的守護精靈, 妖怪們就不會發起攻擊了。具體來說, 無向圖中的每一條邊 ei 包含兩個權值 ai 與 bi 。 若身上攜帶的 a 型守護精靈個數不少於 ai ,且 b 型守護精靈個數不少於 bi ,這條邊上的妖怪就不會對通過這條邊的人發起攻擊。當且僅當通過這片魔法森林的過程中沒有任意一條邊的妖怪向小 e 發起攻擊,他才能成功找到隱士。

由於攜帶守護精靈是一件非常麻煩的事,小 e 想要知道, 要能夠成功拜訪到隱士,最少需要攜帶守護精靈的總個數。守護精靈的總個數為 a 型守護精靈的個數與 b 型守護精靈的個數之和。

輸入檔案的第 1 行包含兩個整數 n, m,表示無向圖共有 n 個節點, m 條邊。

接下來 m 行,第 i + 1 行包含 4 個正整數 xi, yi, ai, bi, 描述第 i 條無向邊。其中xi與yi為該邊兩個端點的標號,ai與bi的含義如題所述。

注意資料中可能包含重邊與自環。

輸出一行乙個整數:如果小 e 可以成功拜訪到隱士,輸出小 e 最少需要攜帶的守護精靈的總個數;如果無論如何小 e 都無法拜訪到隱士,輸出「-1」 (不含引號) 。

【樣例輸入 1】

4 5

1 2 19 1

2 3 8 12

2 4 12 15

1 3 17 8

3 4 1 17

【樣例輸入 2】

3 1

1 2 1 1

【樣例輸出 1】

32 【樣例輸出 2】 -1n

<=

50000,m

<=

100000

簡化一下題意就是每條邊有兩個值(a和b),然後雙關鍵字的最小生成樹,答案要的是兩個的和

可以想到使用lct來解決這道題

先將邊按照a從小到大排序,然後從前往後加邊

加邊時判斷是否成環,如果是就找到環上的b的最大值的邊,如果比當前邊的b大,就切掉這條邊,然後連上當前邊

這就是lct的基本操作了

邊上的值如何用lct維護?再多開乙個點來存就行了

#include

#include

#include

#include

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

#define n 301000

using

namespace

std;

int n,m,father[n],fa[n],p[n],t[n][2],rev[n],c[n],c1[n],b[n],d[n];

struct nodea[n];

bool cnt(node x,node y)

int lr(int x)

void updata(int x)

void down(int x)

void rotate(int x)

void xc(int x,int y)

while(x!=y);

for(;d[0];d[0]--) down(d[d[0]]);

}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 find(int x,int y)

int main()

}else

if(gf(1)==gf(n)) ans=min(ans,a[i].a+a[find(1,n)-n].b);

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

printf("%d",ans);

}

NOI2014 魔法森林

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

NOI2014 魔法森林

noi2014 魔法森林 要求a 與 b 的總和最小 可以按a排序 再以b為權值維護一顆樹 lct維護最小生成樹 要解決的問題 將每一條邊變為乙個點 邊權變為點權 舉個栗子 u v有一條邊權為w的邊 怎lct連邊方式為 u new v new的點權為w 不斷維護最小生成樹 如果新加入的邊的 u與v不...

NOI2014 魔法森林

此題可以用spfa,也可以用lct。可spfa跑得比lct快 學習了一下怎麼把邊權變成點權 新建乙個點表示邊,這個點的點權就是邊權值 原來的點的權值為0 根據題目需要可以為其他值 新增一條邊時,連線兩端的點 刪除一條邊時,需要找到這條邊對應的點編號,兩端刪除 include include incl...