hdu 5424 哈密顿路径

时间:2023-02-02 00:11:05

给n个点,n条边,问是否存在哈密顿路径,即存在一条路径使得所有点只经过一遍,先判断是否连通,再从最小的度数进行dfs

#include<stdio.h>
#include<string>
#include<map>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define rep(i,n) for(int i=0;i<n;i++)
const int N=1e3+10;
const int MOD=1e9+7;
int n,m,k,up;
int cnt[N];
int f[N];
int re;
vector<int> G[N];
int find(int u){
if(f[u]==u)return u;
return f[u]=find(f[u]);
}
bool same(int u,int v){
int u1=find(u),v1=find(v);
return u1==v1;
}
void add(int u,int v){
if(same(u,v) ) return ;
int u1=find(u),v1=find(v);
f[u1]=v1;
}
bool vis[N];
bool check(){
rep(i,n) if(!vis[i]) return false;
return true;
}
bool dfs(int x){
bool ok=false;
for(int i=0;i<G[x].size();i++){
int v=G[x][i];
if(vis[v]) continue;
vis[v]=true;
ok=true;
if(dfs(v)) return true;
vis[v]=false;
}
if(!ok) return check();/*如果找不到可以走的路了,就检查是否所有点都访问过了*/
else return false;
}

bool solve(){
bool ok=true;
rep(i,n) ok&= find(i)==find(0);
if(!ok) return false;/*判断是否为连通图*/
if(re>1) return false;/*自环大于1肯定是不可能的*/

int id=0;
rep(i,n) if(cnt[id]>cnt[i]) id=i;/*找度数最小的边*/

memset(vis,false,sizeof vis);
vis[id]=true;
return dfs(id);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("aaa","r",stdin);
#endif
int T;
while(~scanf("%d",&n)){
int u,v;
memset(cnt,0,sizeof cnt);
rep(i,n) f[i]=i;
re=0;
rep(i,n) G[i].clear();
rep(i,n){
cin>>u>>v;
if(u==v) {re++;continue;}/*去自环*/

u--;v--,cnt[u]++,cnt[v]++,add(u,v);/*加入并查集*/
G[u].push_back(v);
G[v].push_back(u);
}
cout<<(solve()?"YES":"NO")<<endl;
}
return 0;
}