zoukankan      html  css  js  c++  java
  • PTA 06-图3 六度空间 (30分)

    题目地址

    https://pta.patest.cn/pta/test/15/exam/4/question/715

    5-7 六度空间   (30分)

    “六度空间”理论又称作“六度分隔(Six Degrees of Separation)”理论。这个理论可以通俗地阐述为:“你和任何一个陌生人之间所间隔的人不会超过六个,也就是说,最多通过五个人你就能够认识任何一个陌生人。”如图1所示。


    图1 六度空间示意图

    “六度空间”理论虽然得到广泛的认同,并且正在得到越来越多的应用。但是数十年来,试图验证这个理论始终是许多社会学家努力追求的目标。然而由于历史的原因,这样的研究具有太大的局限性和困难。随着当代人的联络主要依赖于电话、短信、微信以及因特网上即时通信等工具,能够体现社交网络关系的一手数据已经逐渐使得“六度空间”理论的验证成为可能。

    假如给你一个社交网络图,请你对每个节点计算符合“六度空间”理论的结点占结点总数的百分比。

    输入格式:

    输入第1行给出两个正整数,分别表示社交网络图的结点数NN(1<Nle 10^41<N104​​,表示人数)、边数MM(le 33 imes N33×N,表示社交关系数)。随后的MM行对应MM条边,每行给出一对正整数,分别是该条边直接连通的两个结点的编号(节点从1到NN编号)。

    输出格式:

    对每个结点输出与该结点距离不超过6的结点数占结点总数的百分比,精确到小数点后2位。每个结节点输出一行,格式为“结点编号:(空格)百分比%”。

    输入样例:

    10 9
    1 2
    2 3
    3 4
    4 5
    5 6
    6 7
    7 8
    8 9
    9 10
    

    输出样例:

    1: 70.00%
    2: 80.00%
    3: 90.00%
    4: 100.00%
    5: 100.00%
    6: 100.00%
    7: 100.00%
    8: 90.00%
    9: 80.00%
    10: 70.00%


    这题BFS又不小心写成了递归。。
    /*
    评测结果
    时间	结果	得分	题目	编译器	用时(ms)	内存(MB)	用户
    2017-07-02 20:39	答案正确	30	5-7	gcc	917	3	
    测试点结果
    测试点	结果	得分/满分	用时(ms)	内存(MB)
    测试点1	答案正确	18/18	2	1
    测试点2	答案正确	3/3	2	1
    测试点3	答案正确	3/3	2	1
    测试点4	答案正确	3/3	2	1
    测试点5	答案正确	3/3	917	3
    
    原题给的数据范围是 1<=N<=10000 ,计算了下,开个10000*10000的数组,可能内存会爆,于是用了链表来遍历。
    结果发现好多人直接开了数组也过了。。。说好的64MB内存的限制呢?莫非编译器神优化?
    
    还有个关键点是BFS过程中,塞入队列的节点要带上深度,否则递归取队列的时候加深度,容易把父结点塞进去的点加上自己的深度,导致深度增长过快。
    
    PS:刚开始评测只过了一个点,百思不得其解,改了半天没发现什么问题。网页上的样例跑的很顺。
    最后没办法在纸上画了个图,新做了组测试数据,有5个结点。
    结果发现。。。。打出来10组数据。输出循环的地方,本来该写N的地方不知道什么时候手贱填了个10。
    突然有种想上吊的感觉。。。
    */
    #include<stdio.h>
    #include<stdlib.h>
    #define MAXN 10001
    #define Q_EMPTY -1
    #define TRUE 1
    #define FALSE 0
    #define DBG //
    typedef struct LinkNode* pLinkNode;
    struct LinkNode
    {
    	pLinkNode next;
    	int data;
    };
    
    
    struct PersonNode //每个人的状态表
    {
    	int visited;
    	pLinkNode head;
    	pLinkNode tail;
    }gPersonTable[MAXN];
    
    struct Queue
    {
    	int head;
    	int tail;
    	int data[MAXN];
    	int level[MAXN]; //该属性维护插入队列时的遍历深度
    } gQueue;
    
    void InitPersonTable() //初始化表,其实没必要。
    {
    	int i;
    	for(i=0;i<MAXN;i++)
    	{
    		gPersonTable[i].head=NULL;
    		gPersonTable[i].tail=NULL;
    		gPersonTable[i].visited=FALSE;
    	}
    }
    
    void ClearVisitFlag() //计算完一个节点的百分比后清空访问数据
    {
    	int i;
    	for(i=0;i<MAXN;i++)
    		gPersonTable[i].visited=FALSE;
    }
    
    void InitQueue()
    {
    	gQueue.head=0;
    	gQueue.tail=0;
    }
    
    void InsertIntoQueue(int x,int level)
    {
    	if((gQueue.tail+1)%MAXN==gQueue.head)
    	{
    		DBG("ERROR:Queue Full!
    ");
    		return;
    	}
    	gQueue.tail=(gQueue.tail+1)%MAXN;
    	gQueue.data[gQueue.tail]=x;
    	gQueue.level[gQueue.tail]=level;
    	DBG("InsertQ:%d,head=%d,tail=%d
    ",gQueue.data[gQueue.tail],gQueue.head,gQueue.tail);
    }
    
    int DeleteQueue()
    {
    	if(gQueue.head==gQueue.tail)
    		return Q_EMPTY;
    	gQueue.head++;
    	DBG("DeleteQ:%d
    ",gQueue.data[gQueue.head]);
    	return gQueue.head;
    }
    
    pLinkNode CreateLinkNode(int x)
    {
    	pLinkNode P=malloc(sizeof(struct LinkNode));
    	P->data=x;
    	P->next=NULL;
    	return P;
    }
    
    void Connect(int a, int b)
    {
    	if(gPersonTable[a].head==NULL)
    	{
    		gPersonTable[a].head=CreateLinkNode(b);
    		gPersonTable[a].tail=gPersonTable[a].head;
    	}
    	else
    	{
    		gPersonTable[a].tail->next=CreateLinkNode(b);
    		gPersonTable[a].tail=gPersonTable[a].tail->next;
    	}
    }
    void BFS(int x,int deepth)
    {
    	DBG("BFS:%d,dep=%d
    ",x,deepth);
    	if(deepth>6 || gPersonTable[x].head ==NULL)
    		return;
    	gPersonTable[x].visited=TRUE;
    	if(deepth==6 )
    		return;
    	pLinkNode P;
    	int newx;
    	P=gPersonTable[x].head;
    	while(P!=NULL)
    	{
    		if(gPersonTable[P->data].visited == FALSE)
    		{
    			InsertIntoQueue(P->data,deepth+1);
    			DBG("Insert %d to Q
    ",P->data);
    			gPersonTable[P->data].visited=TRUE;
    		}
    		P=P->next;
    	}
    	
    	while((newx=DeleteQueue()) != Q_EMPTY)
    	{
    		BFS(gQueue.data[newx],gQueue.level[newx]);
    	}
    }
    
    float CountPercentage(int N) //遍历结点表数数
    {
    	int i,sum;
    	sum=0;
    	for(i=1;i<=N;i++)
    	{
    		if(gPersonTable[i].visited==TRUE)
    			sum++;
    	}
    	DBG("sum=%d
    ",sum);
    	return (float)sum / (float)N*100;
    }
    int main()
    {
    	int N,M,i,a,b;
    	scanf("%d %d",&N,&M);
    	InitPersonTable();
    	InitQueue();
    	for(i=0;i<M;i++)
    	{
    		scanf("%d %d",&a,&b);
    		Connect(a,b);
    		Connect(b,a);
    	}
    	
    	for(i=1;i<=N;i++)
    	{
    		BFS(i,0);
    		printf("%d: %.2f%%
    ",i,CountPercentage(N));
    		ClearVisitFlag();
    		InitQueue();
    	}
    
    }
    

      

  • 相关阅读:
    ADF中遍历VO中的行数据(Iterator)
    程序中实现两个DataTable的Left Join效果(修改了,网上第二个DataTable为空,所处的异常)
    ArcGIS api for javascript——鼠标悬停时显示信息窗口
    ArcGIS api for javascript——查询,然后单击显示信息窗口
    ArcGIS api for javascript——查询,立刻打开信息窗口
    ArcGIS api for javascript——显示多个查询结果
    ArcGIS api for javascript——用图表显示查询结果
    ArcGIS api for javascript——查询没有地图的数据
    ArcGIS api for javascript——用第二个服务的范围设置地图范围
    ArcGIS api for javascript——显示地图属性
  • 原文地址:https://www.cnblogs.com/gk2017/p/7141051.html
Copyright © 2011-2022 走看看