BZOJ3669 Noi2014 魔法森林

2022-05-27 22:21:19 字數 3260 閱讀 1971

n<=50000,m<=100000的圖上,路徑有屬性ai和bi,問從1到n的路徑中(ai的最大值+bi的最大值)的最小值。

雙屬性圖論題,常用套路--定一動二。比如說這裡可以先按a從小到大排序,然後依次加入圖中來考慮怎麼計算b。

方法一:哦,最大值最小,那不是最小生成樹嗎?會加邊的圖,那不是lct維護最小生成樹嗎?

1

//#include

2 #include3 #include4

//#include5//

#include6//

#include7//

#include8//

#include9//

#include

10 #include11 #include12

using

namespace

std;

1314

#define ll long long

15ll qread()

1620

21//

pay attention to '-' , ll and double of qread!!!!

2223

intn,m;

24#define maxn 150011

25struct

lct26

a[maxn];

28int

n;29

void clear(int n)

30void up(int

x)31

35else

if (c.max>=b.v && c.max>=d.max)

36else 37}

38void revsingle(int x)

39void down(int x) }

40bool isroot(int x)

41void rotate(int

x)42

53int

sta[maxn],top;

54void download(int

x)55

59void splay(int

x)60

67rotate(x);68}

69up(x);70}

71void access(int x) splay(z);}

72void reset(int

x) 73

74void link(int x,int y)

75void cut(int x,int

y)76

77bool con(int x,int y) return0;}

78int qmax(int x,int y)

7980

//void test()

81//

85}t;

8687

struct ee }ee[maxn];

88int

main()

8992 sort(ee+1,ee+1+m);

9394

int ans=0x3f3f3f3f

;95 t.clear(n+m);

96for (int i=1;i<=n;i++) t.a[i].v=-0x3f3f3f3f,t.a[i].max=-0x3f3f3f3f,t.a[i].maxid=i;

97for (int i=n+1;i<=n+m;i++) t.a[i].v=ee[i-n].b,t.a[i].max=t.a[i].v,t.a[i].maxid=i;

98for (int i=1;i<=m;i++)

99110

}111

else

112if (t.con(1,n)) ans=min(ans,ee[i].a+t.a[t.qmax(1

,n)].v);

113}

114 printf("

%d\n

",ans==0x3f3f3f3f?-1

:ans);

115return0;

116 }

view code

好久沒寫了,這次寫起來居然這麼順這麼短,有點屌。

方法二:lct學傻了系列,可以先考慮乙個暴力:每次加完邊之後做一次最短路。不過加了一條邊之後,所有導致每個點的答案被更新的根本原因,來自於這條邊兩端的點的互相更新。也就是說,每加一條邊後,前面圖的大部分資訊是不用算的,就看一下這條邊兩端的點能否更新彼此,能的話把被更新的點加入佇列再跑最短路就ok。複雜度??玄學,反正比lct快,好寫!

1 #include

2 #include3 #include4 #include5

//#include

6 #include7 #include8

//#include9//

#include

10using

namespace

std;

1112

intn,m;

13#define maxn 200011

14#define maxm 200011

15struct listlist[maxm];

16bool cmpa(const list &a,const list &b)

17struct edgeedge[maxm]; int first[maxn],le=2;18

void

in(int x,int y,int v)

19void insert(int x,int y,int v)

2021

struct

qnode

2225

};26 priority_queue,greater>q;

27int

dis[maxn];

2829

void kick(int x,int y,int

ev)30

);35}36

}37void

dijkstra()

38);50}

51}52}

53}5455

intmain()

5671

dijkstra();

72 ans=min(ans,list[i].a+dis[n]);73}

74if (ans==0x3f3f3f3f) puts("-1"

);75

else printf("

%d\n

",ans);

76return0;

77 }

view code

bzoj3669 NOI2014 魔法森林

給定n個點m條邊的無向圖,每條邊有兩個權值a與b。求一條1到n的路徑使得路徑經過邊的最大a與最大b的和最小。無法到達輸出 1。n 50000,m 100000。我們嘗試列舉路徑的最大a值,那麼我們只需按照a排序按順序插入,維護1到n的b最大值即可。用並查集維護連通性。當加入j到k這條邊時如果形成環,...

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需要通過這一片魔法森林,才能夠拜訪到隱士。魔法森林中居住了一些妖怪。每當有人經過一條邊的時候,這條...