变异蛮牛

题目链接
 

给定一棵根为 1,且是黑点的有根树。


每个白点相邻所有的点都是黑点,每个黑点相邻所有的点都是白点。换句话说,你可以从根结点开始,按照深度对每个点黑白染色。

现在对于一条两个端点分别是 u,vu,vu,v 的链,定义其长度为:包含的黑点个数 −-− 包含的白点个数。

请你数一数 长度最大 的链的个数。

输入描述:

 

全文第一行是 T(1≤T≤105)T(1\le T\le10^5)T(1≤T≤105),表示数据组数;

接下来 TTT 组数据,先输入一行一个正整数表示树的大小 n(1≤n≤2×105,∑n≤3×106)n(1\le n\le2\times10^5,\sum n\le3\times10^6)n(1≤n≤2×105,∑n≤3×106);


接下来输入 n−1n-1n−1 行每行两个正整数 u,v(1≤u,v≤n)u,v(1\le u,v\le n)u,v(1≤u,v≤n) 表示树的一条边。

输出描述:

输出 TTT 行,每行一个整数表示答案。

示例1

输入

1
6
1 2
2 3
3 4
4 5
5 6

输出

6

说明

合法的链分别是:{1},{3},{5},{1,2,3},{3,4,5},{1,2,3,4,5}

思路:题目说给你链,然后给你n-1条链让这些链连接起来成树,问的是lian的个数,只要在连通块上任意找两点就能连在一起,完全当做lian处理即可,把树当作lian连处理。假设涂黑让x加一,涂白让x减一,可以知道在lian上只要是正数时就是最大长度,也就相当于将黑点挑出来让它们连接组合,只要添加一个变量记录当前黑点个数,然后相加,就能得到连接组合的个数。

数字只会出现0与1来回交替时,用异或

vector数组存图(树):vector数组存图是对邻接矩阵的空间优化,有边权时还要创建结构体来配合记录。

仅有两个端点时:

vector<int>v[N];

int l,r;
cin>>l>>r;
v[l].push_back(r);
v[r].push_back(l);

有边权时:

struct node
{
    int to;
    int w;
}e;

vector<node>G[N];

int l;
cin>>l>>e.to>>e.w;
v[l].push_back(e);

//输出G中的点时,仍需使用node类型来接收
e=G[i][j]//e仍能用
cout<<"from: "<<i<<" to: " <<e.to<<" val: "<<e.w<<endl;

 遍历:

void dfs(int son,int fa,int cl)
{
    for(auto x:v[son])
    {
        if(x!=fa) dfs(x,son,cl^1);
    }
}

完整代码:

#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> pii;
typedef long long ll;
//typedef vector<int> vi;
//#define int long long
#define fir first
#define sec second
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)x.size()
#define rep(i, l, r) for (int i = l; i <= r; ++i)
#define repd(i, l, r) for (int i = l; i >= r; --i)
#define pb push_back


const int N=2e5+10;
vector<int >v[N];
int ans=0;
int temp;

void dfs(int son,int fa,int cl)
{
    if(cl)ans+=++temp;

    for(auto x:v[son])
    {
        if(x!=fa) dfs(x,son,cl^1);
    }
}

void solve()
{
    int n;
    cin>>n;
    rep(i,1,n)
    {
        v[i].clear();
    }
    ans=0;
    temp=0;
    rep(i,1,n)
    {
        int l,r;
        cin>>l>>r;
        v[l].pb(r);
        v[r].pb(l);
    }
    dfs(1,0,1);
    cout<<ans<<endl;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int t;
    cin>>t;
    while(t--)
    {
        solve();
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值