一、题目描述:
给你
你可以选择两个至少有一个相同元素的集合,生成它们的并集,然后这两个集合消失。
求最少多少次合并之后,数字
数据范围:
二、解题思路:
很明显这是一个最短路的题,比赛的时候也是一眼就看出来了。
但是比赛花了一个小时都没调出来,因为建图没建好。
实际上自己画一个图形式就很明了了,数字与集合之间连边,权值为
然后直接跑最短路,时间复杂度
三、完整代码:
1 #include<iostream> 2 #include<queue> 3 #define N 400010 4 #define M 500010 5 using namespace std; 6 int n,m,num,x; 7 int dis[N],vis[N]; 8 //n个集合,m个点 9 //前 n 个点表示集合,后 m 个点表示点 10 struct EDGE{ 11 int v,nxt; 12 }edge[M*2]; 13 int head[N],cnt; 14 void add(int u,int v) 15 { 16 edge[++cnt].v=v; 17 edge[cnt].nxt=head[u]; 18 head[u]=cnt; 19 } 20 struct Node{ 21 int pos,val; 22 bool operator < (const Node &t)const{ 23 return t.val<val; 24 } 25 }; 26 priority_queue <Node> q; 27 void dij(int s) 28 { 29 dis[s]=0; 30 q.push({s,0}); 31 while(!q.empty()) 32 { 33 Node t=q.top(); 34 int u=t.pos,v=t.val;q.pop(); 35 if(vis[u])continue;vis[u]=1; 36 for(int i=head[u];i!=-1;i=edge[i].nxt) 37 if(dis[u]+1<dis[edge[i].v]) 38 { 39 dis[edge[i].v]=dis[u]+1; 40 q.push({edge[i].v,dis[edge[i].v]}); 41 } 42 } 43 } 44 int main() 45 { 46 cin>>n>>m; 47 for(int i=1;i<=n+m;i++) 48 head[i]=-1,dis[i]=1e9; 49 for(int i=1;i<=n;i++) 50 { 51 cin>>num; 52 for(int j=1;j<=num;j++) 53 { 54 cin>>x; 55 add(i,x+n); 56 add(x+n,i); 57 } 58 } 59 dij(n+1); 60 if(dis[n+m]==1e9) cout<<-1<<'\n'; 61 else cout<<(dis[n+m]-2)/2<<'\n'; 62 return 0; 63 }
四、写题心得:
明明是一眼题,比赛的时候却没写出来!!!只有
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】