Robocom-2022初赛-树与二分图

设 G=(V,E) 是一个无向图,如果顶点集合 V 可分割为两个互不相交的子集 (A,B),并且每条边 (i,j)∈E 的两个端点 i 和 j 分别属于这两个不同的顶点子集,则称图 G 为一个二分图。

现在给定一棵树 T,要求选择树中两个没有边相连的结点 i 和 j,使得将无向边 (i,j) 加进 T 后能够构成二分图。你的任务是计算满足这个要求的选择方案有多少种。

输入格式:

输入第一行给出一个正整数 N (2≤N≤106),表示树中结点的个数。

接下来 N−1 行,每行给出树中一条边的两端结点编号,以空格分隔。结点编号从 1 开始。题目保证输入给出的是一棵树中所有的边。

输出格式:

在一行中输出方案数。注意:连接 (1,2) 和 (2,1) 视作同一个方案。

输入样例:

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

输出样例:

4


一、分析

1.求出给出图的二分两个集合的点数量,m和n-m,则可选方案为m*(m-n)-已有的边数(n-1)

2.如何求m:用染色法可以发现点会染成两中颜色,直接按颜色数

3.注意m为LL int ,否则答案部分WA

#include<bits/stdc++.h>
using namespace std;
long long int n,m;
const int N=1e6+10,M=N*2;
int head[N],e[M],ne[M],idx;
bool iscol[N];
int color[N];



//求原始二分图每个集合的点数 m n-m
//可添加的最大边数 sum=m*(n-m)-现有的边数n-1

void add(int a,int b)
{
    e[idx]=b;
    ne[idx]=head[a];
    head[a]=idx;
    idx++;
}


int dfs(int u,int col)
{
    iscol[u]=true;
    color[u]=col;
    if(col==1) m++;
    for(int i=head[u];i!=-1;i=ne[i])
    {
        int j=e[i];
        if(!iscol[j]) {
            if(!dfs(j,3-col)) return 0;
        }
        else if(color[j]==col) return 0;
    }
    return 1;


}

int main()
{
    cin>>n;
    memset(head,-1,sizeof head);
    for(int i=1;i<=n-1;++i)
    {
        int a,b;
        cin>>a>>b;
        add(a,b);
        add(b,a);
    }
    int flag;
    for(int i=1;i<=n;++i)
    {
        if(!iscol[i]) color[i]=1,flag=dfs(i,1);
        if(!flag) break;
    }
    if(flag) cout<<m*(n-m)-(n-1)<<endl;
    else cout<<0;

    system("pause");
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Blossom๑.๑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值