HNOI2019 校園旅行

2022-07-07 04:30:18 字數 1541 閱讀 5739

人生第一道黑題祭

本題偏重思維

判斷回文可以考慮它的遞迴定義

只有乙個字元的串是回文串。

只有兩個字元的串,如果這兩個字元相同,也是回文串;

如果 \(s\) 是回文串,那麼在 \(s\) 的開頭和末尾插入乙個相同的字元,形成的新串也是回文串。

乙個可以想到的方法是設 \(f_\) 表示從 \(x\) 到 \(y\) 可不可行

然後 \(\text\) 列舉邊轉移,\(o(m^2),30pts\)

正解是減少邊

分別考慮 \(0->0,1->1,0->1\) 三種邊形成的連通塊

發現它們都滿足

1.如果連通塊是二分圖(不存在奇環),經過偶環並不會對串的長度的奇偶性造成改變,再加上允許一條邊可以走多次,因此沒有必要保留環,只需保留這個連通塊的乙個生成樹即可。

2.如果連通塊不是二分圖(存在奇環),經過奇環會影響串長度的奇偶性,為了方便處理,我們仍然只保留這個連通塊的生成樹,並在這個連通塊的其中乙個點上加乙個自環(從而留下改變奇偶性的機會)。

以此只保留這些邊

可以證明剩下邊不超過 \(2n-2\) 條(別問我)

然後就沒了

#include#include#includeusing namespace std;

const int n = 5005, m = 500005;

int n, m, q, w[n], f[n][n];

char str[n];

inline void read(int &x)

struct node;

queueq;

int h[n], h[n], x[m], y[m];

struct edgee[m << 1], e[m << 1];

inline void adde(int x, int y)

, h[x] = tote;

}inline void add(int x, int y)

, h[x] = tot;

}int bz1[n], col[n];

void color(int x, int c)

}int fa[n][2];

inline int find(int x, int y)

int bz2[n];

inline void build()

else);

} }for(register int i = 1; i <= n; i++)

if (bz1[abs(col[i])] && !bz2[abs(col[i])]) add(abs(col[i]), abs(col[i])), bz2[abs(col[i])] = 1;

}inline void bfs()

); } }}

int main()

); int x, y;

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

build(), bfs();

for(register int i = 1; i <= q; i++)

}

HNOI2019 校園旅行

某學校的每個建築都有乙個獨特的編號。一天你在校園裡無聊,決定在校園內隨意地漫步。你已經在校園裡呆過一段時間,對校園內每個建築的編號非常熟悉,於是你情不自禁的把周圍每個建築的編號都記了下來 但其實你沒有真的記下來,而是把每個建築的編號除以 2 取餘數得到 0 或 1,作為該建築的標記,多個建築物的標記...

HNOI2019 校園旅行 DP

給定n nn個點,m mm條邊的圖。每個點有0 1 0 10 1的標號,有q qq個詢問,每次詢問點對 u,v u,v u,v 間是否一條路徑 不一定是簡單路徑 滿足路徑經過的點的標號所形成的串是回文串。n 5000,m 5000000 n leq 5000,m leq 5000000 n 5000...

HNOI2019 校園旅行 構造 生成樹 動規

hnoi2019 校園旅行 最樸素的做法就是點對擴充套件 o m 2 發現 n 比較小,我們是否能從 n 下手減少邊數呢?是肯定的 單獨看乙個顏色的聯通塊,如果是二分圖,我們生產樹和原來的效果相同 如果不是二分圖,是會有乙個環的,在樹上隨便圈乙個自環和原來的效果相同 而看不同顏色的連邊,一定是二分圖...