北京市商汤科技开发有限公司面向青少年研发了一款智能伴游机器人-- AI 伴游小精灵。一经推出,深受孩子们的喜爱,可爱又机智的小精灵会想出很多有趣的小游戏来启迪孩子们思考。今天,小精灵给你提出了一个神奇又有趣的多米诺骨牌小游戏。
你手上有一副神奇的多米诺骨牌,数量有 nn个,编号为 1 ~n。它们之间存在着 n−1 个单向推倒关系,即推倒 x 会导致 y 也被推倒,而且这样的关系都满足 x<y,且每组关系中的 y不会重复。
一开始只有 1号骨牌不会被其他骨牌推倒,所以你只需要推倒 1 号骨牌就可以推倒所有的骨牌。
小精灵给你提的问题是:如果我们允许去掉 2个骨牌,那么在最坏情况下你最少需要推倒几个骨牌才能使所有骨牌倒下?
输入格式
第一行输入一个整数 n,表示有 n个多米诺骨牌。
接下来有 n-1 行的输入,每行输入两个整数 x,y,表示x推倒 会导致 y也被推倒。
输出格式
输出一个整数表示去掉两个骨牌之后,最坏情况下你最少需要推倒几个骨牌才能使所有骨牌倒下。
数据规模
n<=5 x 10^3
样例输入
7 1 2 1 3 1 5 2 4 4 7 4 6
样例输出
5
题解:在去掉两个牌之前,推一次一号牌就可以把所有牌推到,去掉的两个牌一定是与其他牌关联次数最多的那两个点(假设这两个点与其它点的给关联次数分别为x1,x2),
去点这两个点之后,那么与这两个点存在关系的点就被孤立了,需要单独推一次,
因此,加上要推的一号牌,去掉两个点之后最多可能要推1+x1+x2次,
还有另外两种特殊情况要考虑一下:
1、如果次数最多的两个牌有一个为一号牌,次数要减一。
2、如果次数最多的两个点存在联系,次数要减一
#include<iostream> #include<algorithm> using namespace std; struct node { int pos; int cnt; }a[5005]; bool cmp(node a,node b) { return a.cnt>b.cnt; } int num[5005],vis[5005][5005]; int main() { int n,x,y; cin>>n; for(int i=1;i<=n;i++)//初始化,使点的号数与下标统一 a[i].pos=i; for(int i=0;i<n-1;i++) { cin>>x>>y; vis[x][y]=1; a[x].cnt++; } sort(a+1,a+n-1,cmp); int x1,x2,ans; x1=a[1].cnt; x2=a[2].cnt; ans=1+x1+x2; if(vis[a[1].pos][a[2].pos]==1)//关联次数最多的两个牌恰好存在推到的关系 ans--; if(a[1].pos==1||a[2].pos==1)//因为一号牌不会被任何牌推倒,如果拿走了一号牌,次数要减一 ans--; cout<<ans<<endl; return 0; }