//先判断是否能成为一棵树,没有多余的节点
//在判断是否生成环
//解决第一个问题,直接合并
//解决第二个问题,查找
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int maxn = 100010;
struct Edge{
int v1, v2;
Edge(int _v1 = 0, int _v2 = 0):v1(_v1),v2(_v2){}
};
Edge E[maxn];
int cnt;
int parent[maxn];
int Rank[maxn];
int sign[maxn];
void Init(){
cnt = 0;
memset(sign, 0, sizeof(sign));
for(int i = 0; i < maxn ;i++){
parent[i] = i;
Rank[i] = 1;
}
}
int findRoot(int x){
int tempRoot;
int root = x;
while(root != parent[root])
root = parent[root];
while(x != root){
tempRoot = parent[x];
parent[x] = root;
x = tempRoot;
}
return root;
}
void Union(int x, int y){
int xRoot = findRoot(x);
int yRoot = findRoot(y);
if(xRoot == yRoot)
return ;
if(Rank[xRoot] < Rank[yRoot])
parent[xRoot] = yRoot;
else if(Rank[xRoot] > Rank[yRoot])
parent[yRoot] = xRoot;
else {
parent[xRoot] = parent[yRoot];
Rank[yRoot] ++;
}
}
void Kruskal(){
int k = 0;
for(int i = 0; i < cnt; ++ i){
if(findRoot(E[i].v1) == findRoot(E[i].v2)){
printf("NO\n");
return ;
}
else {
Union(E[i].v1,E[i].v2);
}
}
for(int i = 0 ; i < cnt; i++ ){
if(sign[E[i].v1] == 0 && E[i].v1 == parent[E[i].v1]){
k++;
sign[E[i].v1] = 1;
}
if(sign[E[i].v2] == 0 && E[i].v2 == parent[E[i].v2]){
k++;
sign[E[i].v2] = 1;
}
}
if(k==1){
printf("YES\n"); return ;
} else {
printf("NO\n");
return ;
}
}
int main(){
int v1, v2;
Init();
while(scanf("%d%d",&v1,&v2)!=EOF){
if(v1 == -1&&v2 == -1) break;
if(v1 == 0 && v2 == 0){
printf("YES\n");
continue;
}
E[cnt++] = Edge(v1,v2);
while(scanf("%d%d",&v1,&v2)&&v1&&v2){
E[cnt++] = Edge(v1,v2);
}
Kruskal();
Init();
}
return 0;
}
//在判断是否生成环
//解决第一个问题,直接合并
//解决第二个问题,查找
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int maxn = 100010;
struct Edge{
int v1, v2;
Edge(int _v1 = 0, int _v2 = 0):v1(_v1),v2(_v2){}
};
Edge E[maxn];
int cnt;
int parent[maxn];
int Rank[maxn];
int sign[maxn];
void Init(){
cnt = 0;
memset(sign, 0, sizeof(sign));
for(int i = 0; i < maxn ;i++){
parent[i] = i;
Rank[i] = 1;
}
}
int findRoot(int x){
int tempRoot;
int root = x;
while(root != parent[root])
root = parent[root];
while(x != root){
tempRoot = parent[x];
parent[x] = root;
x = tempRoot;
}
return root;
}
void Union(int x, int y){
int xRoot = findRoot(x);
int yRoot = findRoot(y);
if(xRoot == yRoot)
return ;
if(Rank[xRoot] < Rank[yRoot])
parent[xRoot] = yRoot;
else if(Rank[xRoot] > Rank[yRoot])
parent[yRoot] = xRoot;
else {
parent[xRoot] = parent[yRoot];
Rank[yRoot] ++;
}
}
void Kruskal(){
int k = 0;
for(int i = 0; i < cnt; ++ i){
if(findRoot(E[i].v1) == findRoot(E[i].v2)){
printf("NO\n");
return ;
}
else {
Union(E[i].v1,E[i].v2);
}
}
for(int i = 0 ; i < cnt; i++ ){
if(sign[E[i].v1] == 0 && E[i].v1 == parent[E[i].v1]){
k++;
sign[E[i].v1] = 1;
}
if(sign[E[i].v2] == 0 && E[i].v2 == parent[E[i].v2]){
k++;
sign[E[i].v2] = 1;
}
}
if(k==1){
printf("YES\n"); return ;
} else {
printf("NO\n");
return ;
}
}
int main(){
int v1, v2;
Init();
while(scanf("%d%d",&v1,&v2)!=EOF){
if(v1 == -1&&v2 == -1) break;
if(v1 == 0 && v2 == 0){
printf("YES\n");
continue;
}
E[cnt++] = Edge(v1,v2);
while(scanf("%d%d",&v1,&v2)&&v1&&v2){
E[cnt++] = Edge(v1,v2);
}
Kruskal();
Init();
}
return 0;
}