CF605B的题解
算是对 Leap_Frog大佬的补充吧qwq。
%%% Leap_Frog.
我们来看一下大佬的这段话:
考虑倒着思考 Kruskal 算法。
按边权从小到大排序。
每次插入一条边。
如果是树边,那就新开节点。
否则在当前节点内任意连边。
这样构造,每次非树边插入都比当前两端小。
所以必然正确。
对于“如果是树边,那就新开节点。”这句话,可以理解成我们构造一个以
就是这样子:
对于“否则在当前节点内任意连边。”这句话,我们插入非树边的时候为了不能重复(题目有要求两点之间不能有多条边),设我们目前已经处理了
放几张图理解一下吧qwq:
这样子代码是不是好理解一点啦qwq.
没有压行的代码(Leap_Frog大佬压行的代码感觉不太好读TaT):
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m;
struct edge
{
int u;
int v;
int w;
int id;
int yes;
}e[100010];
int tot=1;//目前已开的点的数量,我们要设为1,因为我们得先开好1号节点
bool cmp1(edge a,edge b)
{
if(a.w==b.w) return a.yes>b.yes;
return a.w<b.w;
}
bool cmp2(edge a,edge b)
{
return a.id<b.id;
}
int u=2,v=3;//记得初始化
bool flag=1;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&e[i].w,&e[i].yes);
e[i].id=i;
}
sort(e+1,e+1+m,cmp1);
for(int i=1;i<=m;i++)
{
if(e[i].yes) e[i].u=1,e[i].v=++tot;//如果是树边
else//如果是非树边
{
if(v>tot)//无解
{
flag=0;
break;
}
e[i].u=u++;
e[i].v=v;
if(u==v) v++,u=2;
}
}
if(!flag) printf("-1");
else
{
sort(e+1,e+1+m,cmp2);//最后要记得按一开始的输入顺序排序
for(int i=1;i<=m;i++) printf("%d %d\n",e[i].u,e[i].v);
}
return 0;
}
完结撒花~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构