聖戰 奇環, 樹上差分

2021-09-27 01:54:28 字數 2560 閱讀 1362

若 x

xx 與 y

yy 之間有敵對關係, 則在 x

xx 和 y

yy 之間連一條邊, 依此建出乙個圖,

當圖中存在奇環時, 無法完成二染色, 說明無法劃分為 2

22 個合法的陣營,

現在目的就是刪去其中一條邊, 使得圖中不存在奇環, 自然而然的, 刪去的邊是所有奇環,

所以現在需要求出哪些邊是所有奇環.

於 是有

個最初的

做法於是有個最初的做法

於是有個最初

的做法:

利用返祖邊配合樹上差分找出圖中的每個點被奇環覆蓋的次數,

若兩個相連的點都被所有奇環覆蓋, 說明這兩個點之間的邊被所有奇環覆蓋, 刪去這條邊 .

但 是這

樣仍然有

bug但是這樣仍然有bug

但是這樣仍然

有bug

:當刪去某條邊時, 若這條邊在偶環奇環中, 則刪邊後關於這條邊的奇環偶環,偶環奇環,

而新的奇環和 新的偶環組合會形成新的奇環, 這就不合法了 .

所 以所以

所以:當一條邊被所有奇環覆蓋, 且不被任何乙個偶環覆蓋時, 該邊刪去後 存在合法的方案 將圖分為兩個不同的陣營 .

#include

#define reg register

intread()

while

(isdigit

(c)) s = s*

10+ c-

'0', c =

getchar()

;return s * flag;

}const

int maxn =

1e6+10;

int n;

int m;

int cnt;

int num0;

int tmp_1;

int fa[maxn]

;int dep[maxn]

;int head[maxn]

;int cf[maxn][2

];int fa_edge[maxn]

;bool vis[maxn]

;struct edge edge[maxn <<1]

;void

add(

int from,

int to,

int w)

; head[from]

= num0;

}void

dfs(

int k,

int fa)

}void

dfs_2

(int k,

int fa)

}void

dfs_3

(int k,

int fa)

}int

main()

for(reg int i =

1; i <= n; i ++)if

(!vis[i]

)dfs

(i,0);

for(reg int i =

1; i <= n; i ++)if

(!fa[i]

)dfs_2

(i,0),

dfs_3

(i,0);

int ans_1 =

0, ans_2 =0;

if(!cnt)

if(cnt ==

1) ans_1 =

1, ans_2 = tmp_1;

for(reg int i =

1; i <= n; i ++)if

(cf[i][0

]==cnt &&

!cf[i][1

]) ans_1 ++

, ans_2 ^

= fa_edge[i]

;printf

("%d\n%d\n"

, ans_1, ans_2)

;return0;

}

樹上差分的整理(點的樹上差分和邊的樹上差分)

點的樹上差分 若經過 u 到 v 的所有點,tmp u tmp v tmp lca u,v tmp parent lca u,v 0 例題 include using namespace std struct ss ss data 600010 int n,q int a 300010 head 6...

差分 樹上差分略解

差分 樹上差分略解 哈哈差分?先來看一道題 題目描述 給定包含 n個數的陣列 a1,a2,an.有 k次操作 每次操作把區間 l,r 加上v 最後求出數列每個位置的數。輸入格式 第一行,n.第二行,a1,a2,an下一行,k,下k行,每行乙個操作,格式為l,r,v 輸出格式 一行,更新後的陣列 樣例...

差分總結二 樹上差分

找這個樹上 重複經過的最多點 經過幾次 看這名字 就醉了orz 這題是 樹上差分 模板題 點差分 點差分的話 由於 lca 本身是有貢獻的 那麼d lca 用d lca父親 只要消掉影響 include using namespace std const int maxn 1e5 10 int n,...