小白尝试解读Labeling Balls题目大佬的代码(手动惊吓

时间:2019-02-16
本文章向大家介绍小白尝试解读Labeling Balls题目大佬的代码(手动惊吓,主要包括小白尝试解读Labeling Balls题目大佬的代码(手动惊吓使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题目:


题解:有小球若干,编号1–n,要将它们做记号。
有两条约束:
1.每个小球标签不同
2.做记号的时候满足:编号为a的球比编号b的球重量更轻
要求若满足约束条件则输出1–n球的重量

思路:
这道题运用拓扑排序,最后一定要按顺序输出球1–n的 重量
拿样例5做例子

小白缺乏实战经验,借鉴了大佬的代码,一点点理解消化,以下是代码,每行做了一些见解与注释,错误之处望斧正:

#include <iostream>
#include <queue>
#include<cmath>
#include <algorithm>
#include<set>
#include<cstdio>
#include<string.h>
using namespace std;

int out[205];
int map[205][205];
void topo(int n)
{
	int i;
	int cnt=n;//定义最重的小球 
	int weight[205];
	priority_queue<int>q;//优先队列,从大到小排序;
	for(i=1;i<=n;i++)
	{
		if (out[i]==0) q.push(i);//出度为0 与该顶点相关联的边数为0 ,终点 
	} 
	while(!q.empty())
	{
		int k=q.top();//k记录队首编号  下面的weight[]为该编号的重量 
		
		q.pop();//弹出第一结点 k进入下一结点 
		
		weight[k]=cnt--;//小球重量 从大到小排序 
		
		for (i=0;i<=n;i++)
		{
			if (map[i][k])  //  i球与k球的重量作对比 
			{
				out[i]--;
				if (out[i]==0) q.push(i);
			}
		} 	
	}
	if (cnt>0) printf("-1\n"); 
	else 
	{
		for(i=1;i<n;i++) printf("%d ",weight[i]);
		printf("%d\n",weight[i]);	
	}
}
int main()
{
	int sample;
	cin>>sample;
	int n,m,i,j;
	int a,b;
	while(sample--)
	{
		cin>>n>>m;//n为小球个数,m为约束个数 
		memset(out,0,sizeof(out));
		memset(map,0,sizeof(map)); //两行为初始化 
		while(m--)
		{
			cin>>a>>b;
			if (map[a][b]==0)//map为约束表 
			{
				map[a][b]=1; //a比b轻  ,map记录a、b关系 
				out[a]++;  //编号为b的球排在a后,所以a的出度加1 
			}
		}
		topo(n);
		
		
	}

	
	return 0;
}
代码作者:Rocky0429