洛谷 P7443 加邊 題解

2022-09-14 18:54:07 字數 2822 閱讀 8472

洛谷原題

這題算是我想出來的吧,慶祝一下!

首先思考如果沒有加邊的情況該怎麼做,那自然是乙個典型的「有向圖遊戲」,用一遍樹形dp即可解決。

具體來說,設某一方現在處於點\(x\),下一步輪到他走,則\(dp(x)=1\)表示他必勝,\(dp(x)=0\)表示他必敗。

若\(\forall y \in son(x)\),都有\(dp(y)=1\),那麼\(dp(x)=0\)。

若\(\exists y\in son(x)\),滿足\(dp(y)=0\),那麼\(dp(x)=1\)。

接下來考慮有加邊的情況。發現加的邊無非分成三類:返祖邊、橫插邊、下插邊。我們一類一類討論。

返祖邊。返祖邊會使得樹中存在乙個環。可以發現,這類邊是沒有意義的。設返祖邊為\((x,y)\),則\(dp(x)\)一定等於0。這是因為既然要把邊新增到\(x\),那\(x\)肯定是必敗狀態,我才會試圖改變我必敗的命運。而且既然當前已經走到了\(x\),說明之前肯定是從\(y\)不得不走下來的,即兩個人都採取最優策略的情況下從\(y\)走下來的。所以經過邊\((x,y)\)之後,兩個人肯定也會「不得不」從\(y\)沿著樹邊重新走回\(x\)。這樣就死迴圈了,仍然改變不了我必敗的命運。

橫插邊。要想讓橫插邊\((x,y)\)有意義,首先必須滿足的條件是\(dp(x)=0\)且\(dp(y)=0\)。\(dp(x)=0\)的原因和返祖邊類似,不再贅述。\(dp(y)=0\)的原因是,我要達到乙個目的:我走完\((x,y)\)這條邊之後,你是必敗局面。

下插邊。同上。

我們再來考慮一下如果想讓alice贏,我們要把邊插到哪些點上。

alice先手。

若\(dp(root)=1\),則不必加邊。

若\(dp(root)=0\),則我希望當我把橫插邊或下插邊插在某乙個點\(x\)上時,\(x\)會從必敗局面轉變為必勝局面,而且這個變化最終會導致根節點從必敗狀態轉變為必勝狀態。思考後會發現,\(x\)是滿足條件的點,當且僅當\(dp(x)=0\),且\(x\)的所有兄弟的\(dp\)值是1。不僅\(x\)是這樣,\(x\)的爺爺也必須這樣,\(x\)的爺爺的爺爺也必須這樣,\(x\)的爺爺的爺爺的爺爺也必須這樣……

alice後手。

若\(dp(root)=0\),則不必加邊。

若\(dp(root)=1\),同「alice先手」。

把這些點標記後,對於某乙個被標記的點\(x\),我們只需找出除了\(x\)祖先之外的、滿足dp值是0的點中,點權最小的那乙個。更新答案即可。

考慮這個東西怎麼找。

我們維護乙個全域性變數\(minn\)。在訪問完乙個點\(x\)後,再用\(x\)的點權更新\(minn\)。正反兩次dp即可。這不是我們強調的重點。

時間複雜度\(o(n)\)。

#include #include #include #include using namespace std;

#define int long long // 嘿嘿嘿

#define mem(s, v) memset(s, v, sizeof s)

inline int read(void)

while (ch >= '0' && ch <= '9')

return f * x;

}const int maxn = 2e5 + 5, inf = 2e18 + 1;

int t, n, t, a, b;

int a[maxn], ans;

bool tag[maxn];

bool valid[maxn];

int minn;

vectorlinker[maxn];

inline void clear(void)

mem(valid, 0);

ans = inf;

minn = inf;

}void dfs(int x)

}void dfs2(int x, int fa)

}if (cnt == 1 && valid[fa]) valid[pos] = true;

for (int i = 0; i < (int)linker[x].size(); ++ i)

}void dfs3(int x)

if (minn != inf && valid[x]) ans = min(ans, a * a[x] + b * minn);

if (!tag[x]) minn = min(minn, a[x]);

}void dfs4(int x)

if (minn != inf && valid[x]) ans = min(ans, a * a[x] + b * minn);

if (!tag[x]) minn = min(minn, a[x]);

}signed main()

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

dfs(1);

if (t == 0)

valid[1] = true;

dfs2(1, 0);

dfs3(1);

minn = inf;

dfs4(1);

printf("%lld\n", ans == inf ? -1 : ans);

}else

valid[0] = true;

dfs2(1, 0);

dfs3(1);

minn = inf;

dfs4(1);

printf("%lld\n", ans == inf ? -1 : ans);}}

return 0;

}

洛谷 P1101 題解

這道題可以用深搜 回溯 來寫,相信大部分人都是這麼想的,但是有些人可能在一些地方饒了半天,所以這裡就貼一下我的思路,個人覺得自己的很好懂,除了tx和ty那裡,但是tx和ty的那種用法對於輸出路徑的題目一般很實用 這個算是比較簡單的吧,題目裡給出了具體要找的字串,我們要做的就是對它進行8個方向的搜尋,...

洛谷 P1169 題解

請你在乙個黑白矩陣中選出乙個長方形 含正方形 和正方形的子矩陣,使得所有相鄰的點顏色不一樣。矩陣大小 兩條邊都 2000 2000 2 000輸入 3 31 0 1 0 1 0 1 0 0輸出4 6解釋給定矩陣 正方形 長方形 我的控制台是萌萌噠 ffc0cb粉色 乙個小技巧 如果您的控制台是像我的...

題解 洛谷 P3332

題目描述 權值線段樹套線段樹板子題 首先觀察題目,判斷為二維偏序問題 操作1為區間修改,所以一定是外部線段樹維護權值,內部線段樹維護所在區間,否則時間複雜度 qwq 為方便查詢,雜湊時我採用雜湊每個數的相反數的方法將求第k大轉換為求第k小 詢問可以直接想到的做法就是二分答案,查詢1 ans在區間內的...