洛谷原題
這題算是我想出來的吧,慶祝一下!
首先思考如果沒有加邊的情況該怎麼做,那自然是乙個典型的「有向圖遊戲」,用一遍樹形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在區間內的...