题意:给出一个有向图,这个有向图图的限制条件为任意两点之间只能存在一条有向边,问从任意点出发并且每个点只能走一次,问最长的路径是什么,答案不唯一,输出一个即可;
这道题仔细分析题意可以知道,如果把这个有向图的方向去掉,那么这个无向图就是一个完全无向图。如果以前遇见过竞赛图,那么肯定就知道了这就是竞赛图,我也是才知道的,百度了一下竞赛图是什么东西:
那么竞赛图就有一个特点:
所以就知道了是一个哈密尔顿图:能从一个点开始经过所有点,并且点只经过一次。
所以就知道了这个最长的路径长度就是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;
}