HDU 5424 Rikka with Graph II 哈密顿路径+dfs找环

来源:互联网 发布:足球博客软件 编辑:程序博客网 时间:2024/06/05 07:40
HDU 5424
题意:给出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;elseb[++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 0x3f3f3f3fusing 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;}


原创粉丝点击