题目链接(https://nanti.jisuanke.com/t/52314)

有 n 个人,其中有 m 对相互认识的关系。

一个人的知名度定义为 有多少人 和他相互认识。

现在蒜头君需要从这 n 个人中选出三个人成为火枪手,需要相互认识,但是在这个基础上又希望他们三个人的知名度总和加起来最低。

输入格式

第一行为两个整数 n,m,都不大于 4000。

往后 m 行每一行输入两个不超过 n 的整数 x,y(x<y),表示第 x,y 两人互相认识(数据中有可能会有重复的认识关系)。

对于 50% 的数据,满足 n,m<=200。

对于 100% 的数据,满足 n,m≤4000。

输出格式

如果能找到三个相互认识的人,你需要输出所有选择中 知名度总和的最低值,否则输出 -1。

*输出时每行末尾的多余空格,不影响答案正确性

样例输入1
5 6
1 2
1 3
2 3
2 4
3 4
4 5

样例输出1
8

样例输入2
7 4
2 1
3 6
5 1
1 7

样例输出2
-1
题目来源
计蒜客信息学 1 月入门赛

思路

首先我们看输出的条件:三个相互认识的人知名度总和最低

接着搞清楚什么是“三个相互认识的人”:由题目可知,输入的x,y(x<y),即x与y相互认识。

三个互相认识:也就是说,设三个人为1,2,3,若他们三个相互认识,就要输入三次:①x=1,y=2 ②x=2,y=3 ③x=1,y=3.

然后搞清楚什么是知名度总和最低
题目指出:一个人的知名度定义为 有多少人 和他相互认识。
也就是说输入一次x和y,x和y的知名度分别加1。
我们可以用个桶来统计。

但是有个特殊情况:数据中有可能会有重复的认识关系
之后再说处理方法。

注意:要审清题目:“如果能找到三个相互认识的人,你需要输出所有选择中 知名度总和的最低值,否则输出 -1。”
意思就是:输出三个互相认识的人中知名度总和的最低值而不能理解为如果三个知名度最小的人没有都互相认识,就输出-1。

做法

用到统计,枚举,结构体,选择排序等方法。

1.依照题目意思,暴力枚举O(n^3)

#include <iostream>
using namespace std;
#define size 5000
int a[size];
struct guns{int f[size];
}g[size];//我们可以用一个结构体来统计一个枪手的信息,若g[x].f[y]>0则记x与y认识。 struct know{int a,b,c;
}kn[size];//定义一个结构体表示一组三个互相认识的人a,b,cint main(){int n,m,x,y;cin>>n>>m;for(int i=0;i<m;i++){cin>>x>>y;g[x].f[y]++;g[y].f[x]++;}//输入加统计O(n) //特殊情况处理:从guns入手   O(n^2)for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)if(g[i].f[j]>0) a[i]++;//查找三个互相认识的人O(n^3)暴力枚举 bool flag=0;//标记有无三个互相认识的人 int top=0;//指向kn的最后一组的下一位for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++)for(int k=j+1;k<=n;k++)if(g[i].f[j]>0&&g[j].f[k]>0&&g[i].f[k]>0){kn[top].a=i;kn[top].b=j;kn[top].c=k;top++;flag=1;}//没有三个互相认识的人 if(!flag){cout<<-1;return 0;}//从三个互相认识的人组中筛出最小知名度int min=a[kn[0].a]+a[kn[0].b]+a[kn[0].c]; for(int i=1;i<top;i++){int sum=a[kn[i].a]+a[kn[i].b]+a[kn[i].c];if(min>sum) min=sum;}cout<<min;return 0;
}

能过5组数据,其余超时。

我们从枚举的地方看看有什么优化的地方。
要查找三个互相认识的人可以尝试从x和y入手。
因为x和y认识。
我引出了一种想法:
将所有x和y储存到一起,比较x(x<y),从小到大排序。
就拿样例输入1来说:
a b 下标(i)
1 2 0
1 3 1
2 3 2
2 4 3
3 4 4
4 5 5

它已经是有序的了。
先从i=1开始循环,若i=0时的a不等于i=1时的a(if(a[i]!=a[i-1])),就continue。
否则就是说明1认识2,1认识3,而此时只要判断g[2].f[3]>0?就能得出三个互相认识的人了。

特殊情况:
a b
1 2
1 3
1 4
2 3
2 4
3 4
4 5
此时,当i到达a=1,b=4时,则还需要多一个循环判断a=1,b=3和a=1,b=2的情况。
则这个想法的时间复杂度为O(n^2)

2.O(n^2)优化`

#include <iostream>
#include <algorithm>
using namespace std;
#define size 5000
int a[size];
struct guns{int f[size];
}g[size];//我们可以用一个结构体来统计一个枪手的信息,若g[x].f[y]>0则记x与y认识。 struct xxy{int x,y;
}xy[size];//储存x和y struct know{int a,b,c;
}kn[size];//定义一个结构体表示一组三个互相认识的人a,b,cint main(){int n,m,x,y;cin>>n>>m;for(int i=0;i<m;i++){cin>>x>>y;g[x].f[y]++;g[y].f[x]++;xy[i].x=min(x,y);//题目虽说x<y,但是样例输入2给的真是不行 xy[i].y=max(x,y);}//输入加统计O(n) //特殊情况处理:从guns入手   O(n^2)for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)if(g[i].f[j]>0) a[i]++;//给储存xy的结构体排序,这里用的是选择排序 for(int i=0;i<m;i++){for(int j=i+1;j<m;j++){if(xy[j].x<xy[i].x) swap(xy[i],xy[j]);}}int top=0;//查找三个互相认识的人O(n^2)bool flag=0;//标记是否有三个互相认识的人 for(int i=1;i<m;i++){for(int j=i-1;j>=0;j--){if(xy[i].x!=xy[j].x) continue;//此时j遍历到0是没有关系的 //如果xy[i].y认识xy[j].yif(g[xy[i].y].f[xy[j].y]>0){kn[top].a=xy[i].x;kn[top].b=xy[i].y;kn[top].c=xy[j].y;top++;flag=1;}}}//没有三个互相认识的人 if(!flag){cout<<-1;return 0;}//从三个互相认识的人组中筛出最小知名度int min=a[kn[0].a]+a[kn[0].b]+a[kn[0].c]; for(int i=1;i<top;i++){int sum=a[kn[i].a]+a[kn[i].b]+a[kn[i].c];if(min>sum) min=sum;}cout<<min;return 0;
}

这样就过了,不知道是不是可以用树来解决,但是妹学。

计蒜客一月入门赛:《三个火枪手》题解相关推荐

  1. 计蒜客信息学入门赛 #16--B

    蒜头君报名参加了折纸兴趣小组, 他表现出了极大的热情,折出了 nn 件折纸作品. 他的作品只有 33 种,分别是长方形.正方形和三角形. 现在蒜头君很想知道他的 nn 件折纸的周长之和. 输入格式 第 ...

  2. 计蒜客信息学入门赛 #17--B

    蒜头君平时勤工俭学,在两家店 A,BA,B 里都有兼职,蒜头君一天只会去一家店里打工,现在告诉你蒜头君每天的打工情况,请你帮他计算一下,他最多连续多少天是去同一家店打工的? 输入格式 只有一行由 A, ...

  3. 计蒜客信息学入门赛 #16--C--最大区间包含问题--待完善

    蒜头君的工厂需要生产 nn 个产品,每个产品会在记录本上记录开始生产的时间 xx 以及完成生产的时间 yy. 现在蒜头君拿到这本记录本以后想知道最多有多少件产品同时在生产线上生产. 注意:在同一时刻总 ...

  4. 计蒜客NOIP模拟赛 数三角形

    数三角形 题目描述 刚刚上高中的洁洁在学习组合数学的过程中遇到一道麻烦的题目,她希望你能帮助她解决.给定一张无向完全图 G,其中大部分边被染成蓝色,但也有一些边被染成红色或者绿色.现在,洁洁需要给这张 ...

  5. 计蒜客NOIP模拟赛(2) D1T1邻家男孩

    凡是一个具有领导力的孩子.现实生活中他特别喜欢玩一个叫做 UNO 的纸牌游戏,他也总是带着其他小朋友一起玩,然后战胜他们.慢慢地,他厌倦了胜利,于是准备发明一种新的双人纸牌游戏. 初始时,每个人手中都 ...

  6. 计蒜客NOIP模拟赛(2) D2T2紫色百合

    [问题描述] "牵着你的手的是她,路边开满了紫色的百合花--" 你从梦中醒来,却依然忘不了梦中的她百合花,每朵百合花都有一个权值,在二进制下写成一行'1',第i朵紫色百合的权值在二 ...

  7. 计蒜客NOIP模拟赛4 D2T2 跑步爱天天

    YOUSIKI 在 noip2016 的一道<天天爱跑步>的题爆零后,潜心研究树上问题,成为了一代大师,于是皮皮妖为了测验他,出了一道题,名曰<跑步爱天天>. 有一个以 1 为 ...

  8. 【计蒜客信息学模拟赛1月月赛 - B】蒜头套圈圈(贪心,前缀最大值)

    题干: 蒜头去嘉年华玩儿套圈圈,是这么玩儿的.有一些瓶口口径不同的啤酒瓶,瓶子里面有一些奖品.如果蒜头用手上的圈圈套中了啤酒瓶,那么奖品就归他了. 假设蒜头君无限精准,指哪儿打哪儿,并且蒜头了解到,只 ...

  9. 【计蒜客信息学模拟赛1月月赛 - D】Wish(dp计数,数位)

    题干: 如果一个数大于等于 10且任意连续两位都是质数,那么就称之为 Wish 数.当然,第一个 Wish 数是 11. 比如 97,111,131,119 都是 Wish 数,而 12,136 则不 ...

最新文章

  1. [LeetCode]: 53: Maximum Subarray
  2. rabbitmq在web管理界面登录失败login fail
  3. 一次公司内部的Tech Talk中涉及到的关于语言的发展问题
  4. 贪心1--排队打水问题
  5. 经典项目|手撸一个高质量RPC框架
  6. eigen库安装_OpenCV+Eigen上位机程序移植(七十一)
  7. 2019年南大计算机开放日_开放式硬件计算机年
  8. C语言学习笔记---打印函数printf()和sprintf()函数
  9. c++的set_unexpected不起作用
  10. 一个月薪两万的Web安全工程师要掌握哪些技能?
  11. 实习程序员工资2.5K,公司团建还要自己掏钱:领导以为你爱吃泡面
  12. 关于发那科机器人弧焊指令故障处理
  13. 怎么对linux系统的硬盘检测,详解Linux系统中hdparm硬盘检测工具的使用
  14. mob做php短信接口,【PHP】短信接口(正则匹配)
  15. ijkplayer 代码走读之 h264 解封装器应用详解
  16. 路由器,你身边的“地雷”?
  17. Java面试那点事——网络200302
  18. 信息学奥赛一本通 第五版(C++版)
  19. C#利用zedgraph绘制曲线
  20. Android-WakeLock(唤醒锁与CPU休眠/屏幕常亮)

热门文章

  1. 沈国军标签:零售业叛徒 马云的朋友 无所不能的怪兽
  2. 利用Vue.js实现简单员工管理系统(增删查)的功能
  3. 也碰到了刷新后再闪烁的问题
  4. 【C语言】C语言成长之路之关于C语言的操作符以及一些表达式的讲解(՞• •՞).
  5. Flutter时间轴-首个
  6. 粗读Image Projection Network: 3D to 2D Image Segmentation in OCTA Images
  7. 怎么学会查看建筑图纸?dwg建筑图怎么打开?
  8. ipados 蓝牙 android,iPadOS13.4如何连接蓝牙鼠标 iPadOS13.4蓝牙鼠标连接使用教程
  9. Outlook 显示Working Offline?
  10. 利用LruCache为GridView异步加载大量网络图片完整示例