解题报告【pat-1076】

最近一直在忙项目都没时间好好总结写博客,说起来真实惭愧啊。

下面就把自己最近做的几题好好总结一下,主要记录一些注意点,以防以后遇到再犯。

1076. Forwards on Weibo (30)

时间限制

3000 ms

内存限制

32000 kB

代码长度限制

16000 B

判题程序

Standard

作者

CHEN, Yue

Weibo is known as the Chinese version of Twitter.  One user on Weibo may have many followers, and may follow many other users as well.  Hence a social network is formed with followers relations.  When a user makes a post on Weibo, all his/her followers can
view and forward his/her post, which can then be forwarded again by their followers.  Now given a social network, you are supposed to calculate the maximum potential amount of forwards for any specific user, assuming that only L levels of indirect followers
are counted.

Input Specification:

Each input file contains one test case.  For each case, the first line contains 2 positive integers: N (<=1000), the number of users; and L (<=6), the number of levels of indirect followers that are counted.  Hence it is assumed that all the users are numbered
from 1 to N.  Then N lines follow, each in the format:

M[i] user_list[i]

where M[i] (<=100) is the total number of people that user[i] follows; anduser_list[i] is a list of the M[i] users that are followed by user[i].  It is guaranteed that no one can follow oneself.  All the numbers are separated
by a space.

Then finally a positive K is given, followed by K UserID‘s for query.

Output Specification:

For each UserID, you are supposed to print in one line the maximum potential amount of forwards this user can triger, assuming that everyone who can view the initial post will forward it once, and that only L levels of indirect followers
are counted.

Sample Input:

7 3
3 2 3 4
0
2 5 6
2 3 1
2 3 4
1 4
1 5
2 2 6

Sample Output:

4
5

这个题目的坑在题意不好理解,尤其是像我这种英语比较拙计的人。最后查了几个单词总算理解了题意,本质上就是做搜索。但是涉及到一个是选择dfs还是bfs的问题。刚开始没多想,感觉差不多,后来就用了dfs。

dfs需要注意的几点:

【1】邻居存储数据结构的选择,这里用了邻接表,比较清楚。

【2】注意不能存在回路的情况,比如说1是4的粉丝,4也是1的粉丝。如果先1后4,那么到4的时候就不应该回去再访问1!也就是不能存在回路。

【3】在不能存在回路的基础上,要考虑一种特殊情况,5-1-4 这时候L==0了,也就是说到了限定的最外层。这时候不能再往下搜索,应该退回到5。但是4的邻居此时没有被搜索过。若5的下一个邻居是4,这时候4也要被访问,因为4的邻居可能存在没被访问过的点。

为了解决环路问题,同时兼顾【3】我们设一个点有3种状态

#define  discover 0
#define  cnted 1
#define  undsicover 2

每次访问一个点若该点为 undsicover,那么置为dsicover并cnt++,如果该点本身是dsicover,那么说明存在回路,不再继续。一个点回退后要置为cnted。避免下次访问被跳过,即【3】的情况。

代码:

// pat-1076.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include"iostream"
#include "vector"
#include "algorithm"
#include "fstream"
using namespace std;
#define  discover 0
#define  cnted 1
#define  undsicover 2
int cnt=0;
class node{
public:
	int id;
	vector<node*> neiber;
	int statues;
	node():neiber(NULL),statues(undsicover),id(-1){}
};

void resetall(node* an,int n)
{
	for (int i=0;i<n+1;i++)
	{
		an[i].statues=undsicover;
	}
	cnt=0;
}

void forward(node* p,int l)
{
	if (p->statues==discover||l==0)//避免形成回环
	{
		return;
	}
	if ((p->statues==undsicover))//false
	{
		cnt++;//计数加一
		p->statues=discover;//cnted
	}
	if (p->neiber.empty())//没有邻居不用遍历
	{
		return;
	}
	int len=p->neiber.size();
	for (int i=0;i<len;i++)
	{
		forward(p->neiber[i],l-1);//dfs
	}
	p->statues=cnted;
}

int main()
{
	fstream fcin;
	fcin.open("C:\\Users\\Administrator\\Desktop\\456.txt");

	int n=0,l=0;
	fcin>>n>>l;
	node *an=new node[n+1];//编号从1-n
	for (int i=1;i<=n;i++)
	{
		an[i].id=i;
	}
	for (int i=1;i<=n;i++)
	{
		int temp=0,j=0;
		fcin>>temp;
		while(temp--)
		{
			fcin>>j;
			an[j].neiber.push_back(&an[i]);//作为目标的邻居而不是把目标作为自己的邻居
		}
	}
	int k=0,index=0;
	fcin>>k;
	for(int i=0;i<k;i++)
	{
		fcin>>index;
                forward(&an[index],l+1);
		cout<<cnt-1<<endl;
		resetall(an,n);
	}
	return 0;
}

上述算法的逻辑没错,但是最后一个点会超时!!!呵呵,随后又写了一个bfs版本的。

// pat-1076.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include"iostream"
#include "vector"
#include "algorithm"
#include "fstream"
#include "queue"
using namespace std;
#define  discover 0
#define  cnted 1
#define  undsicover 2
int cnt=0;

class node{
public:
	int id;
	vector<node*> neiber;
	int statues;
	node():neiber(NULL),statues(undsicover),id(-1){}
};

void resetall(node* an,int n)
{
	for (int i=0;i<n+1;i++)
	{
		an[i].statues=undsicover;
	}
	cnt=0;

}

void bfs(node* p,int l)
{
	queue<vector<node*>> q;
	queue<vector<node*>> qq;
	p->statues=discover;
	q.push(p->neiber);
	while(!q.empty())
	{
		if (qq.empty())
		{
			l--;
			qq=q;
		}
		if (l==0)
		{
			return ;
		}
		vector<node*> v=q.front();
		q.pop();
		qq.pop();

		int len=v.size();
		for (int i=0;i<len;i++)
		{
			if (v[i]->statues==undsicover)
			{
				cnt++;
				v[i]->statues=discover;
				if (!v[i]->neiber.empty()&&l>0)
				{
					q.push(v[i]->neiber);
				}

			}
		}
	}
}

int main()
{
	fstream fcin;
	fcin.open("C:\\Users\\Administrator\\Desktop\\456.txt");

	int n=0,l=0;
	fcin>>n>>l;
	node *an=new node[n+1];//编号从1-n
	for (int i=1;i<=n;i++)
	{
		an[i].id=i;
	}
	for (int i=1;i<=n;i++)
	{
		int temp=0,j=0;
		fcin>>temp;
		while(temp--)
		{
			fcin>>j;
			an[j].neiber.push_back(&an[i]);//作为目标的邻居而不是把目标作为自己的邻居
		}
	}
	int k=0,index=0;
	fcin>>k;
	for(int i=0;i<k;i++)
	{
		fcin>>index;
		bfs(&an[index],l+1);
		cout<<cnt<<endl;
		resetall(an,n);
	}
	return 0;
}

这个是可以ac的,果然递归是个坑啊!但是这里涉及到一个计算bfs深度的问题。在dfs里面这很自然,递归的深度就是目前所处树的深度。但是在用stack实现的bfs算法里面没有可用的量。所以这里用了比较笨的办法,开了两个stack,一个是用来计数的。还好stl重载了运算符=,否则代码会有点啰嗦。

如果大家有什么跟好的想法,欢迎交流!

解题报告【pat-1076】,布布扣,bubuko.com

时间: 2024-10-05 04:45:04

解题报告【pat-1076】的相关文章

pat解题报告【1074】

1074. Reversing Linked List (25) 时间限制 300 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L.  For example, given L being 1→2→3→4→5→

pat解题报告【1073】

1073. Scientific Notation (20) 时间限制 100 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 HOU, Qiming Scientific notation is the way that scientists easily handle very large numbers or very small numbers.  The notation matches the regular expression [

pat解题报告【1078】

1078. Hashing (25) 时间限制 100 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue The task of this problem is simple: insert a sequence of distinct positive integers into a hash table, and output the positions of the input numbers.  The hash fun

pat解题报告【1082】

1082. Read Number in Chinese (25) 时间限制 400 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Given an integer with no more than 9 digits, you are supposed to read it in the traditional Chinese way.  Output "Fu" first if it is negative. 

2016.8.29 解题报告之我会做的题都是简单题

老规矩,要相关资料联系邮箱: 考试分析: 1.  画图确定性质,其实我开始也打算用二进制判重的,但进制题一般不会使状态无法用longlong表示出来,然后那种确定了某种状态以后就排除了无关变量,直接取最优的思路也很不错: 2.  最早入手的题以及死在上面的题,还想了了很久的复杂度证明和对拍,无话可说,希望这次AK之路被断能让我涨一点记性,以后要抓住脑海里的每一点信息(本来还想了longlong这个问题的): 3.  找性质,把在线决策问题转化为线性判断类问题,排除任务之间有一点橡树的关系的无关干

解题报告 之 POJ3057 Evacuation

解题报告 之 POJ3057 Evacuation Description Fires can be disastrous, especially when a fire breaks out in a room that is completely filled with people. Rooms usually have a couple of exits and emergency exits, but with everyone rushing out at the same time

hdu 1541 Stars 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1541 题目意思:有 N 颗星星,每颗星星都有各自的等级.给出每颗星星的坐标(x, y),它的等级由所有比它低层(或者同层)的或者在它左手边的星星数决定.计算出每个等级(0 ~ n-1)的星星各有多少颗. 我只能说,题目换了一下就不会变通了,泪~~~~ 星星的分布是不是很像树状数组呢~~~没错,就是树状数组题来滴! 按照题目输入,当前星星与后面的星星没有关系.所以只要把 x 之前的横坐标加起来就可以了

【百度之星2014~初赛(第二轮)解题报告】Chess

声明 笔者最近意外的发现 笔者的个人网站http://tiankonguse.com/ 的很多文章被其它网站转载,但是转载时未声明文章来源或参考自 http://tiankonguse.com/ 网站,因此,笔者添加此条声明. 郑重声明:这篇记录<[百度之星2014~初赛(第二轮)解题报告]Chess>转载自 http://tiankonguse.com/ 的这条记录:http://tiankonguse.com/record/record.php?id=667 前言 最近要毕业了,有半年没做

2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告

2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告 勘误1:第6题第4个 if最后一个条件粗心写错了,答案应为1580. 条件应为abs(a[3]-a[7])!=1,宝宝心理苦啊.!感谢zzh童鞋的提醒. 勘误2:第7题在推断连通的时候条件写错了,后两个if条件中是应该是<=12 落了一个等于号.正确答案应为116. 1.煤球数目 有一堆煤球.堆成三角棱锥形.详细: 第一层放1个, 第二层3个(排列成三角形), 第三层6个(排列成三角形), 第四层10个(排列成三角形). -. 假设一共