AtCoder Beginner Contest 173 比赛人数10755 比赛开始后6分钟看到所有题
AtCoder Beginner Contest 173 F Intervals on Tree 树上的乘法原理(打通任督二脉)
总目录详见https://blog.csdn.net/mrcrack/article/details/104454762
在线测评地址https://atcoder.jp/contests/abc173/tasks/abc173_f
题目大意:给出一棵树,提供点的信息,边的信息,设S是编号为L到R的顶点集。f(L,R)表示仅由顶点集S和端点都属于S的边构成的子图中连通分量的个数。计算:
样例解释如下:
Input:
3
1 3
2 3
Output:
7
For L=1,R=1, S={1} and we have 1 connected component.如下图,只有1个连通分量
For L=1,R=2, S={1,2} and we have 2 connected components.如下图,有2个连通分量
For L=1,R=3, S={1,2,3} and we have 1 connected component, since S contains both endpoints of each of the edges 1,2.如下图,只有1个连通分量
For L=2,R=2, S={2} and we have 1 connected component.如下图,只有1个连通分量
For L=2,R=3, S={2,3} and we have 1 connected component, since S contains both endpoints of Edge 2.如下图,只有1个连通分量
For L=3,R=3, S={3} and we have 1 connected component.如下图,只有1个连通分量
总共有7个连通分量。
该样例对应的构造算法如下:
Input:
3
1 3
2 3
Output:
7
1.只有孤立点,没有边参与的连通分量如下:
1.1只选一个点{1},{2},{3},对应有1*3=3(1表示选择的节点数量,3表示对应的种类)个连通分量。1*(3-1+1)=1*3=3
1.2只选两个点{1,2},{2,3},对应有2*2=4(2表示选择的节点数量,2表示对应的种类)个连通分量。2*(3-2+1)=2*2=4
1.3只选三个点{1,2,3},对应有3*1=3(3表示选择的节点数量,1表示对应的种类)个连通分量。3*(3-3+1)=3*1=3
总的连通分量是3+4+3=10
2.边参与,导致的连通分量减少过程如下
2.1边(1,3)参与。边(1,3)会影响到{1,2,3}此种情况,导致该种情况的连通分量数少1.
考虑1 2 3节点,1的左边有1个数(包括1),3的右边有1个数(包括1),对应的连通分量减少1*1=1.
2.2边(2,3)参与。边(2,3)会影响到{2,3},{1,2,3}这两种情况,导致总的连通分量数少2.
针对2.2进一步的说明如下:
考虑1 2 3节点,2的左边有2个数(包括2),3的右边有1个数(包括1),对应的连通分量减少2*1=2.
针对2.2更进一步的说明如下:
(1 2 3)这种组合影响{1,2,3},(2 3)这种组合影响{2,3},故对应的连通分量减少2*1=2.
综合上述两种情况,对应的连通分量是10-1-2=7
根据上述构造算法,编写的AC代码如下:
#include <cstdio>
#include <algorithm>
#define LL long long
using namespace std;
LL ans;
int main(){
int n,i,u,v;
scanf("%d",&n);
for(i=1;i<=n;i++)ans+=(LL)i*(n-i+1);//i表示每次选择点的个数,(n-i+1)表示选择点集的可能数量。若无连线,全是孤立点,对应不同的连通分量。
for(i=1;i<n;i++){
scanf("%d%d",&u,&v);
if(u>v)swap(u,v);//无向图,让边的节点,左小右大,方便处理
ans-=(LL)u*(n-v+1);//乘法原理,等价于(u-1+1)*(n-v+1).u-1+1代表区间[1,u]内的节点个数.(n-v+1)代表区间[v,n]内的节点个数
}
printf("%lld\n",ans);
return 0;
}