題意:給一個樹,可以從里面刪去兩個點,使連通塊數量最大
思路:題解:CF2063C Remove Exactly Two - 洛谷專欄
這道題很容易想到,直接刪去度最多的兩個點就行了,但是這并不對,因為相鄰點被刪去之后,會導致自己的度數-1,所以刪去的第一個點和第二點都要好好考慮,本人就是沒考慮第一個點對第二個點的影響,第一個點選擇錯了,可能第二點永遠選不出最佳,反例就是三個度相同的點在一起,你不能選中間那個
因此轉換思路,第一個點不貪心選,而是暴力枚舉,第二個點貪心選擇即可,不能兩個點都貪心選,是不正確的,連通塊可以直接計算得到,也好想
代碼:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define IOS \std::ios::sync_with_stdio(0); \std::cin.tie(0); \std::cout.tie(0)const int N = 3e5 + 5;
const int INF = 1e18;
const int MOD = 998244353;
// const int MOD=1e9+7;
// const int MOD=100003;
const int maxn=5e5+10;std::vector<int> ve[N];
int a[N];void solve(){int n;std::cin >> n;for(int i=1;i<=n;i++){a[i]=0;ve[i].clear();}for(int i=0;i<n-1;i++){int x,y;std::cin >> x >> y;ve[x].push_back(y);ve[y].push_back(x);a[x]++,a[y]++;}multiset<int> se;for(int i=1;i<=n;i++){se.insert(a[i]);}int ans=0;for(int i=1;i<=n;i++){int sum=1;se.erase(se.find(a[i]));for(auto v : ve[i]){se.erase(se.find(a[v]));se.insert(a[v]-1);}sum+=a[i]-1;sum+=*se.rbegin()-1;for(auto v : ve[i]){se.erase(se.find(a[v]-1));se.insert(a[v]);}se.insert(a[i]);ans=std::max(sum,ans);}std::cout << ans << '\n';}signed main()
{IOS;int t = 1;std::cin >> t;while (t--){solve();}
}