題意:
給定一棵無根樹,求用最少的鏈覆蓋樹上所有的邊,並輸出每條鏈的首位兩端編號
做法:
首先確認需要多少條鏈來覆蓋所有邊。
顯然,當n = 1時,只需要一條,鏈頭尾編號都為1
當n = 2時,需要一條,鏈頭尾為1, 2
當n >= 3時,上述兩種情況鏈的頭尾都是入度為1的點,而確實,當從乙個葉子節點1出發,向上走到假定的根節點,再往下走到葉子節點2,如此反覆形成的鏈,足以覆蓋所有的邊,並確為最少情況。
但此法僅於葉子節點為偶數時適用,如何在葉子節點個數為奇數時確定最少鏈數,只需讓根節點和最後剩餘的葉子節點成鏈即可。
對於每個葉子節點分配乙個dfs序,用dfn陣列記錄,找到乙個非葉子節點作為根節點,把乙個樹分成假定的左右子樹,讓每條鏈的兩端分別處於左右不同的子樹即可。
遍歷一棵樹的時間複雜度o(n)
code
1 #include 2#define dbg(x) cout << #x << "=" << x << endl
3#define eps 1e-8
4#define pi acos(-1.0)56
using
namespace
std;
7 typedef long
long
ll;8
9const
int inf = 0x3f3f3f3f;10
11 templateinline void read(t &res)
1217
18namespace
_buff
26return ib == ie ? -1 : *ib++;27}
28}2930
intqread()
38if (c == '-'
) 42
for (; c >= '
0' && c <= '
9'; c =getc())
45return pos ? ret : -ret;46}
4748
const
int maxn = 2e5 + 7;49
50 vectorg[maxn];
51int
n;52
53int
du[maxn];
54int
dfn[maxn];
55int
vis[maxn];
56int cnt = 0;57
58void dfs(int u, int
fa)
65 vis[v] = 1;66
dfs(v, u);67}
68if(d == 1
) 71}72
73int
main()
7483
int root = -1;84
int num = 0;85
for ( int i = 1; i <= n; ++i ) 89}
90for ( int i = 1; i <= n; ++i ) 95}
96int ans = num / 2;97
if(num & 1
) 100
if(n == 1
) 104
if(n == 2
) 108 dfs(root, -1
);109
//for ( int i = 1; i <= cnt; ++i )
112int mid = (cnt + 1) >> 1
;113
//dbg(mid);
114 cout << ans <115for ( int i = 1; i <= cnt - mid; ++i )
118if(cnt & 1
) 121
return0;
122 }
2018 牛客多校 2
problem a problem b 考慮第二種優惠,每乙個物品如果原價購買了,那麼向可以免費拿的那個物品連一條邊 在樹上被指向的那個點是父親 如果不考慮環的話,考慮樹上dp。設 f i 0 表示買掉以 i 為根的子樹需要的最小花費,設 f i 0 表示買掉以 i 為根的子樹並且 i 這個點是原價...
牛客多校1 1or2
題意 給定一張n點m邊的圖,以及每個點的理想出入度,求是否能夠通過選擇某些邊來使得新圖上每個點的出入度為理想出入度 做法 由於d i 的範圍為1 2,說明新圖中的連通分量要麼是鏈,要麼是環。對於此類最大匹配問題,可以用網路流來解決,但是由於可能存在奇環,這將導致找增廣路時,傳統的dinic演算法時間...
牛客多校2Eddy Walker 2
線性遞推的下界 bm演算法 複雜度 k 2 logn 正常矩陣快速冪 k 3 logn k 表示每一項由前k項遞推得到 n代表要得到的項 看到咖啡雞的 把前2 k 1項扔進去就可以了。include define maxn 100005 define inf 1000000000 define mo...