Rikka with Graph II
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1051 Accepted Submission(s): 266
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?
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(1≤n≤1000).
Then n lines follow. Each line contains two numbers u,v(1≤u,v≤n) , which means there is an edge between u and v.
For each testcase, the first line contains a number n(1≤n≤1000).
Then n lines follow. Each line contains two numbers u,v(1≤u,v≤n) , 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
题目大意:就给你n个顶点,n条边,问你是不是可以在图中找到哈密顿路径。
解题思路:对于n条边的图,如果要形成哈密顿路径,则必然要用掉n-1条边,形成一条链,起点和终点的度为1,其余点的度为2。剩下的一条边,可能有下面的情况:
情况1:形成自环,自环对于哈密顿路径没影响,可以忽略。
情况2:形成重边,重边对于哈密顿路径也没影响,可以忽略。
情况3:起点或终点跟非终点或非起点连一条边,这时候从终点或起点dfs。
情况4:起点跟终点连边,所有点的度都为2,从任意点dfs。
吐糟:自己写的时候vector清空的时候放在了最后,因为中间有continue,结果就呵呵了。。。一直超时,纳闷死了。再者就是没有考虑清楚,开始写的时候没有把所有路径都走完,会漏掉情况,不该呀~~~
#include<bits/stdc++.h> using namespace std; const int maxn=2100; const int INF=0x3f3f3f3f; int degree[maxn]; int vis[maxn],gra[maxn][maxn]; vector<int>G[maxn]; int n; bool dfs(int u,int fa,int cn){ if(cn==n){ return true; } for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(vis[v]||v==fa){ continue; } vis[v]=1; if(dfs(v,u,cn+1)) return true; vis[v]=0; //如果没有这句,会过不了这个样例。5 2 3 2 4 4 1 1 2 5 4 } return false; } void init(){//以后尽量放在前面情况,不装B for(int i=0;i<=n+2;i++) G[i].clear(); memset(degree,0,sizeof(degree)); memset(vis,0,sizeof(vis)); memset(gra,0,sizeof(gra)); } int main(){ int a,b; while(scanf("%d",&n)!=EOF){ init(); for(int i=0;i<n;i++){ scanf("%d%d",&a,&b); if(gra[a][b]==1||a==b) continue; gra[a][b]=gra[b][a]=1; G[a].push_back(b); G[b].push_back(a); degree[a]++,degree[b]++; } int deg1=0,idx=1; for(int i=1;i<=n;i++){ if(degree[i]==1){ deg1++; idx=i; } } if(deg1>2){ //度为1的大于2个,必然不行 puts("NO"); continue; } vis[idx]=1; if(dfs(idx,0,1)) puts("YES"); else puts("NO"); } return 0; }