最近学校网课跟得紧没时间写知识点,就拿题解凑个数(bushi
而且前两天我打着打着题解电脑就突然死机 幸运的是 我没有保存(微笑)
废话不多说 上题目!
城市攻击
(city)
(256MB,1s)
【问题描述】
出于某些原因,A国将对B国进行攻击。B国有n个城市,有n-1
双向条道路,每条道路连接两个城市,任意两个城市可以通过道路
互相到达,即构成一棵树。由于资金有限,A国只能攻击B国的两个
城市,攻击后这两个城市将会毁灭,与这两个城市连接的道路也随
之消失,A国希望在攻击后能将B国分成尽可能多的连通块,这样有
利于A国的下一步行动,于是他们找到你来完成这个任务。
【输入格式】
输入文件名为city.in
第一行包含一个整数T,表示数据组数。
对于每组数据
第一行包含一个整数n,表示B国城市的数量。
接下来n-1行,每行两个整数x,y,表示有一条道路连接城市x与城市y
【输出格式】
输出文件名为city.out
输出文件包含T个整数,表示对于每组数据,攻击两个城市后最多能
使B国分成多少个连通块
【输入样例】
city.in city.out
2
5
1 2
2 4
3 4
4 5
7
1 2
2 3
1 4
1 5
3 6
3 7
3
5
【数据规模与约定】
对于20%的数据T<=5,1≤n≤100
对于50%的数据T<=5,1≤n≤1000
对于100%的数据T<=10,1≤n≤100000
看到这个题说实话我考试的时候二话不说直接爆搜= =
但后来老师一讲就发现其实有窍门
具体看我的详(la)细(ji)题解:
1 //通过画图可以看出我们要通过删除度数最多的城市点来拆分连通块,在枚举过程中发现删除xy会得到d[x]+d[y]-n个连通块 2 //且两点相连时n为2两点不连时n为1 3 //max分别列举情况 判断即可 4 #include<cstdio> 5 #include<cstdlib> 6 #include<cstring> 7 #include<iostream> 8 using namespace std; 9 struct node// 10 { 11 int y,next;//y代表目标位, next的意义参照day3-例1 12 }a[2000010]; 13 int first[1000010],len;// first【x】从x出发的第一条边 14 int d[1000010];//度数 15 void ins(int x,int y)//边列表 16 { 17 a[++len].y=y; 18 a[len].next=first[x]; 19 first[x]=len; 20 } 21 bool is_conected(int x,int y)//判断两点之间有没有联系 22 { 23 int k; 24 for(k=first[x];k;k=a[k].next) 25 if(a[k].y==y)return 1; 26 return 0; 27 } 28 int main() 29 { 30 freopen("city.in","r",stdin); 31 freopen("city.out","w",stdout); 32 int o,n,i,j,k,x,y; 33 scanf("%d",&o);//数据组数 34 while(o--) 35 { 36 scanf("%d",&n);//B国城市数量 37 for(i=1;i<=n;i++) first[i]=d[i]=0;//先全部清空一遍 38 len=0;//清空 39 for(i=1;i<n;i++) 40 { 41 scanf("%d%d",&x,&y); 42 ins(x,y);ins(y,x);//存储他们的边 因为是无向图 所以当做双向用 43 d[x]++;d[y]++;//x,y的度数分别加1 44 } 45 int max_d=0,sec_d=0;//max代指目前度数最大的点 sec代指度数第二大的点 _d代指这个度数的值 46 int max_s=0,m1,m2;//max_s代表目前最大点的个数 m1记录第一个最大点的编号 m2代表第二个 当这两个点都有存储时代表有两个及以上,如果最大度数的点有三个及以上不用记录 一定有两个最大度数点不相连 47 int sec_s=0;//第二大度数的点的个数 48 for(i=1;i<=n;i++)//记录最大度数的点的个数以及第二大度数的点的个数 49 { 50 if(d[i]>max_d)//扫描到的点的度数如果比当前的最大的度数值要大 51 { 52 sec_d=max_d; 53 sec_s=max_s;//当前的“最大”度数变成第二大,更新第二大的度数点的相关数据 54 max_d=d[i]; 55 max_s=1;m1=i;//更新最大度数点 m1更新 56 } 57 else if(d[i]==max_d) 58 { 59 max_s++;//最大度数的点的个数+1 60 if(max_s==2)m2=i;//m2更新 61 } 62 else if(d[i]>sec_d)//更新第二大的度数代表的一系列数据 63 sec_d=d[i],sec_s=1; 64 else if(d[i]==sec_d) 65 sec_s++; 66 }//如果又else 什么都不用做 67 68 if(max_s>=3){printf("%d ",2*max_d-1);continue;} 69 if(max_s==2) 70 { 71 if(is_conected(m1,m2))//判断两点是否相连 72 printf("%d ",2*max_d-2); 73 else printf("%d ",2*max_d-1); 74 continue; 75 } 76 //max_s=1;无需判断,直接操作 77 int s=0; 78 for(k=first[m1];k;k=a[k].next)//扫描从x出发的第一条边开始 意为消除第一个城市然后确定连通块数量 79 { 80 y=a[k].y; 81 if(d[y]==sec_d) s++;//这两步的意思是寻找与x相连的sec,s为计数点 82 } 83 if(s==sec_s)//如果与max连接的点的数量与总的点的数量一样 84 printf("%d ",max_d+sec_d-2);//出推论 85 else printf("%d ",max_d+sec_d-1);//反之,出推论 86 } 87 return 0; 88 }
好了大概就这么多
但是这个题没A,why?
因为!
我不会离散化(哭了)
好了如果你喜欢这篇题解别忘了点赞投币收藏……
诶?好像跑题了= =