Longest Path(竞赛图+哈密尔顿图+list求路径)

在这里插入图片描述在这里插入图片描述在这里插入图片描述
题意:给出一个有向图,这个有向图图的限制条件为任意两点之间只能存在一条有向边,问从任意点出发并且每个点只能走一次,问最长的路径是什么,答案不唯一,输出一个即可;
这道题仔细分析题意可以知道,如果把这个有向图的方向去掉,那么这个无向图就是一个完全无向图。如果以前遇见过竞赛图,那么肯定就知道了这就是竞赛图,我也是才知道的,百度了一下竞赛图是什么东西:
在这里插入图片描述
那么竞赛图就有一个特点:在这里插入图片描述
所以就知道了是一个哈密尔顿图:能从一个点开始经过所有点,并且点只经过一次。
所以就知道了这个最长的路径长度就是v-1,v是顶点个数,那么经过的顶点肯定就是所有顶点了,并且一定存在一条路径;
所以我觉得题解用的list来维护就很巧妙了;
下面就是题解的解说:
在这里插入图片描述
根据这个题解的意思我可以明白这点:
在这里插入图片描述
一个相邻的点,前驱节点肯定指向这个点,这个点肯定指向后继节点;
所以直接用到list跑一次即可出答案;
不得不说用list维护,确实太巧妙了;
AC代码:

#include<bits/stdc++.h>
using namespace std;
int Map[510][510];
list<int> List;
int main(){
    
    
	int T;
	scanf("%d",&T);
	while(T--){
    
    
		int v;
		scanf("%d",&v);
		for(int i=1;i<=v;i++){
    
    //初始化图 
			  for(int j=1;j<=v;j++){
    
    
			  	scanf("%d",&Map[i][j]);
			  }
		}
		List.push_back(1);//从1号节点出发 
		for(int i=2;i<=v;i++){
    
    
			   int out=0,in=0;
			   for(list<int>::iterator it=List.begin();it!=List.end();it++){
    
    
			   	  if(Map[i][*it])out++;//i点 指向链表里面的个数 
			   	  else in++;//链表里面的指向i点的个数 
			   }
			   //cout<<in<<""<<out<<endl;
			   if(out==List.size())List.push_front(i);//如果i点指向List中的所有点 
			   else if(in==List.size())List.push_back(i);//如果i点被List中的所有点指向 
			   else{
    
    
			   	list<int>::iterator it=List.begin(),next;
			   	   for(;;it++){
    
    
					    next=it;next++;
					      if(next==List.end())break;
					      if(Map[*it][i]&&Map[i][*next]){
    
    
					      	 break; 
						  }
					  }
			   	   List.insert(next,i);//加入两个点之间,如果没有那么就加在最后面
			   }
		}
		for(list<int>::iterator it=List.begin();it!=List.end();it++){
    
    
			printf("%d ",*it);
		}
		puts("");
		List.clear();
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_44555205/article/details/104555076

相关文章