HDU 5424
题意:给出n点n条边的图,问是否存在哈密顿路径(经过每个点正好一次) n<=1e3.
n个点n条边,先找到图中的环(自环没用),则环上最多只能有两个点度数==3
不在环上的点 度数不能超过3.图形向"只"形状 显然有解.
法2:如果原图不是环 则起点和终点度数都为1.暴力从度为1的开始搜 判断是否正好走过n个点
题意:给出n点n条边的图,问是否存在哈密顿路径(经过每个点正好一次) n<=1e3.
n个点n条边,先找到图中的环(自环没用),则环上最多只能有两个点度数==3
不在环上的点 度数不能超过3.图形向"只"形状 显然有解.
dfs时 用栈保存当前未遍历完的点 如果u-v v在栈内 则从栈中v开始到u为一个环.
#include <bits/stdc++.h>
using namespace std;
const int N=1e3+5;
int n,cnt,deg[N],b[N];
bool vis[N],cir[N],ins[N],o;
vector<int> e[N*2];
map<int,int> mp[N];
stack<int> sta;
void init()
{
for(int i=1;i<=n;i++)
e[i].clear(),deg[i]=0,vis[i]=0,cir[i]=0,ins[i]=0,mp[i].clear();
o=cnt=0;
}
void dfs(int u,int fa)
{
if(o)
return;
sta.push(u);
ins[u]=1,vis[u]=1;
for(int i=0;i<e[u].size();i++)
{
int v=e[u][i];
if(v==fa)
continue;
if(!vis[v])
dfs(v,u);
else if(ins[v])
{
while(!sta.empty())
{
int cur=sta.top();
cir[cur]=1;
sta.pop();
if(cur==v)
break;
}
o=true;
return;
}
}
if(o)
return;
sta.pop();
ins[u]=0;
}
int main()
{
while(cin>>n)
{
init();
int u,v;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&u,&v);
if(mp[u][v])
continue;
mp[u][v]=mp[v][u]=1;
if(u==v)
continue;
deg[u]++,deg[v]++;
e[u].push_back(v);
e[v].push_back(u);
}
dfs(1,0);
bool flag=true;
for(int i=1;i<=n;i++)
{
if(deg[i]>3)
flag=false;
if(deg[i]==3)
{
if(!cir[i])
flag=false;
else
b[++cnt]=i;
}
}
if(cnt>2)
flag=false;
if(cnt==2&&(!mp[b[1]][b[2]]))
flag=false;
printf(flag?"YES\n":"NO\n");
}
return 0;
}
法2:如果原图不是环 则起点和终点度数都为1.暴力从度为1的开始搜 判断是否正好走过n个点
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
#define N 1010
#define INF 0x3f3f3f3f
using namespace std;
int n, G[N][N], du[N], f;
bool vis[N];
void Init()
{
memset(G, 0, sizeof(G));
memset(du, 0, sizeof(du));//du[i]记录点i的入度
memset(vis, false, sizeof(vis));
}
void DFS(int u, int cnt)
{
int i;
vis[u] = true;
if(cnt == n)//访问次数与点的个数相等,则每个点都访问到了,且每个点只访问了一次
{
f = 1;
return ;
}
for(i = 1 ; i <= n && !f ; i++)
{
if(!vis[i] && G[u][i])
{
DFS(i, cnt + 1);
vis[i] = false;
}
}
}
int main()
{
int u, v, i;
while(~scanf("%d", &n))
{
Init();
for(i = 1 ; i <= n ; i++)
{
scanf("%d%d", &u, &v);
if(u != v && !G[u][v])//去除自环和重边的情况
{
G[u][v] = G[v][u] = 1;
++du[u];
++du[v];
}
}
int s = 1, num = 0;//s记录度最小的点
for(i = 1 ; i <= n ; i++)
{
if(du[i] == 1)
{
num++;//统计度为1的点的个数
s = i;
}
}
if(num > 2)
{
printf("NO\n");//判断其不连通,则不是哈密顿通路
continue;
}
f = 0;
DFS(s, 1);//从度最小的开始搜
if(f == 1)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}