寫了個亂搞,怎麼莫名其妙就ac了,這...,之後又想了30min結合題解終於會證了。
首先最大值比較簡單,記 \(f_i\) 為第 \(i\) 個點能到達的點數,上界 \(\sum_^n f_i\) 一定可以取到。考慮取到是這麼一件事情,如果 \(b_x=y\) 那麼 \(y\) 一定不能是 \(x\) 在外向樹上的祖先以及環上的節點,外向樹的根的前驅例外。那麼有這麼乙個貪心,列舉每一棵外向樹,用乙個棧維護當前節點可以匹配的節點,一開始前驅在棧中。對於每乙個節點,先優先匹配完其子樹,然後再從棧中選取乙個節點給它匹配。這樣保證了如果存在完美匹配,一定不存在會令乙個點取不到 \(f_i\) 的情況。然後證明,這樣一定有完美匹配,考慮每乙個節點,如果其不是葉子,那麼其一定可以與其的某個孩子匹配。如果是葉子,那麼只有遍歷到第乙個的葉子時候棧中不存在非其祖先節點,其餘情況因為之前已經遍歷了至少乙個葉子,所以之前的到它的路徑上至少遇到了乙個孩子數量 \(>1\) 的節點,而一棵外向樹做完以後至少會提供乙個未匹配節點,這個葉子必然可以與那個未匹配節點匹配。最後再讓第乙個遍歷到的葉子與前驅匹配即可。
最小值比較難,考慮這麼一件事情,乙個節點如果與其子樹中的節點匹配,則會使答案減少 \(f_i-1\) ,如果外向樹的根 \(x\) 與環上某個節點 \(y\) 匹配,則會使答案減少 \(lenth-dis(x,y)\) 。還是類似的構造方法,只不過將原來 \(x\) 和 \(y\) 匹配改成 \(y\) 和 \(x\) 匹配。考慮乙個葉子節點,其一定不能和子樹內匹配。考慮乙個非葉子節點,其一定可以和其乙個兒子匹配。特殊的,如果一棵外向樹只有乙個點,它可以與環上的後繼匹配,這樣使 \(len-dis(x,y)\) 取到最大,這樣我們保證了只要能取 \(f_i-1\) 就一定取到,不能取到的情況下也取到了最優的值,這是個緊的下界。
用棧是因為在求最大值的過程中,即使不匹配兒子也是可以的,但是求最小值的過程中要嚴格與兒子匹配,所以用棧維護未匹配點可以保證這一點,複雜度 \(\mathcal o(n)\) 。
code
/*program by mangoyang*/
#include #define inf (0x7f7f7f7f)
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template inline void read(t &x)
const int n = 200005;
ll ans, ans2;
stackst;
vectorg[n];
int vis[n], ins[n], inc[n], f[n], dep[n], c[n], b[n], n;
inline int getcircle(int u, vector&a)
return ins[u] = 0, 0; }
inline void mark(int u)
inline void gao(int u, int fa, int lenth)
b[u] = st.top(), st.pop();
if(flag) ans2 -= f[u] - 1;
if(!flag && !fa) ans2 -= lenth - 2;
}int main()
} for(int i = 1; i <= n; i++) c[b[i]] = i;
printf("%lld\n", ans2);
for(int i = 1; i <= n; i++) printf("%d ", c[i]);
puts("");
printf("%lld\n", ans);
for(int i = 1; i <= n; i++) printf("%d ", b[i]);
}
UER 2 資訊的交換
吉利題.不難發現,置換中的每乙個迴圈是獨立的,每乙個迴圈分別對應乙個獨立的聯通塊。根據題目的性質,每乙個聯通塊做的事情等價於其按照編號從小到大遍歷的的dfs生成樹做的事情,那麼只需要考慮一棵dfs生成樹做的事情即可。對於一棵dfs生成樹,將每個點的兒子按照編號從小到大排序,考慮節點 u 以及它的兒子...
Problem Zju1082 謠言的傳播
problem zju1082 謠言的傳播 time limit 1 sec memory limit 128 mb submit status web board china歷史最偉大的spy金無怠潛入了美國的fbi,為了整掉這個罪惡的機構,他決定在fbi散布假訊息。他首先選定fbi中的某乙個職員...
113 UER 2 手機的生產
uoj 傳送門 蒟蒻做這個題是一懵一懵的啊。題意就好難懂!我們以 為分界線,分成若干塊。因為在每一小塊中有0這一塊的返回值就是0,在整個表示式中有某一塊的返回值為1,那整個式子就是1,剩下的塊都不用算了。只有當手機返回值為1時才能造出手機。而且在當前這塊中複製出的手機,在下一塊中才能造出其他的手機。...