1. 程式人生 > >hdu5424 Rikka with Graph II(n個點n條邊的圖判哈密頓通路)

hdu5424 Rikka with Graph II(n個點n條邊的圖判哈密頓通路)

Rikka with Graph II

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 547    Accepted Submission(s): 134


Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

Yuta has a non-direct graph with n
 vertices and n edges. Now he wants you to tell him if there exist a Hamiltonian path.

It is too difficult for Rikka. Can you help her?
Input There are no more than 100 testcases. 

For each testcase, the first line contains a number n(1n1000).

Then n lines follow. Each line contains two numbers u
,v(1u,vn)
 , which means there is an edge between u and v.

Output For each testcase, if there exist a Hamiltonian path print "YES" , otherwise print "NO".
Sample Input 4 1 1 1 2 2 3 2 4 3 1 2 2 3 3 1
Sample Output NO YES Hint For the second testcase, One of the path is 1->2->3 If you doesn't know what is Hamiltonian path, click here (https://en.wikipedia.org/wiki/Hamiltonian_path).
Source 中文題意:

Rikka with Graph II

   Accepts: 44    Submissions: 586  Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) 問題描述
眾所周知,萌萌噠六花不擅長數學,所以勇太給了她一些數學問題做練習,其中有一道是這樣的:

勇太有一張nn個點nn條邊的無向圖,現在他想要知道這張圖是否存在一條哈密頓路徑。

當然,這個問題對於萌萌噠六花來說實在是太難了,你可以幫幫她嗎?
輸入描述
資料組數不超過100組。每組資料的第一行一個整數n(1 \leq n \leq 1000)n(1n1000)。

接下來nn行。每行兩個整數u,v(1 \leq u,v \leq n)u,v(1u,vn),代表給定圖上的一條邊。
輸出描述
對於每一組資料,如果圖中存在一條哈密頓路徑,輸出"YES"否則輸出"NO"。
輸入樣例
4
1 1
1 2
2 3
2 4
3
1 2
2 3
3 1
輸出樣例
NO
YES
Hint
第二組資料的一條哈密頓路徑是1->2->3

如果你不知道哈密頓路徑是什麼,戳這裡(https://en.wikipedia.org/wiki/Hamiltonian_path).
官方題解:

Rikka with Graph II

如果圖是聯通的,可以發現如果存在哈密頓路徑,一定有一條哈密頓路徑的一端是度數最小的點,從哪個點開始直接DFS搜尋哈密頓路徑複雜度是 O(n)O(n)的。要注意先判掉圖不連通的情況。

程式設計思想(參考自:http://blog.csdn.net/u014679804/article/details/48092393):

給一個n條邊,n個頂點的圖,判定是否存在哈密頓路。

如果存在哈密頓路,此時路徑中含有n-1條邊,剩下的那一條要麼是自環(這裡不予考慮,因為哈密頓路必然不經過),要麼連線任意兩個點。不考慮自環,此時圖中的點度數為1的個數必然不超過2個,有如下三種情況:

1、剩下的那條邊連線起點和終點,此時所有點度數都是2,可以從任意一個頂點開始進行DFS,看能否找到哈密頓路

2、剩下的那條邊連線除起點和終點外的任意兩個點,此時起點和終點度數為1,任選1個開始進行DFS。

3、剩下的那條邊連線起點和除終點的任意一個點,或者連線終點與除起點外的任意一個點,此時圖中僅有1個點度數為1,從該點開始進行DFS即可。


AC code:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int n;
bool vis[1010];
int deg[1010];
int Map[1010][1010];
int fg;
void dfs(int u,int cnt)
{
	vis[u]=true;
	if(cnt==n)
	{
		fg=1;
		return;	
	}
	for(int i=1;i<=n&&!fg;i++)
	{
		if(!vis[i]&&Map[u][i])
		{
			dfs(i,cnt+1);
			vis[i]=false;
		}
	}
}
int main(){
   //freopen("in.txt","r",stdin);
   int i,u,v;
   while(scanf("%d",&n)!=EOF)
   {
   	    memset(deg,0,sizeof(deg)); 
   	    memset(vis,0,sizeof(vis));  
		memset(Map,0,sizeof(Map));
   		for(i=1;i<=n;i++)
   		{
   			scanf("%d%d",&u,&v);
   			if(u!=v&&!Map[u][v])//排除自環和重邊 
   			{
				deg[u]++;
				deg[v]++;
				Map[u][v]=Map[v][u]=1;
			}
		}
		int tot=0;
		int st=1;
		for(i=1;i<=n;i++)
		{
			if(deg[i]==1)
			{
				tot++;
				st=i;
			}	
		}
		if(tot>2)
			puts("NO");
		else
		{
			fg=0;
			dfs(st,1);//從度數為1的點開始深搜 
			if(fg)
			{
				puts("YES");
			}
			else
			{
				puts("NO");
			}
		}
   }
   return 0;
}