题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=129
是不是要满足三个条件:
1、只有一个根结点,如果有多个则是森林;
2、除根结点外其他的节点入度只能是1,如有其它,则不是;
3、结点数-边数=1,主要是确保每一个节点只有一个父节点。还要注意空树也是一颗树~~
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAX=10010;
#define CLR(arr,val) memset(arr,val,sizeof(arr));//这是学的聪神的做法,呵呵呵~~他的博客是:http://blog.acmol.com~非常推荐看!!
int indgree[MAX],sign[MAX],father[MAX],rank[MAX],sum=1;
void Init()
{ for(int i=0;i<MAX;i++)
{ father[i]=i;
rank[i]=1;
sign[i]=0;//标记点i是否用到
}
}
int Find(int u)
{ return father[u]==u?u:Find(father[u]);
}
void Union(int u,int v)
{ u=Find(u);
v=Find(v);
if(u==v) return ;
if(rank[u]>rank[v])
{ rank[u]+=rank[v];
father[v]=u;
}
else
{ rank[v]+=rank[u];
father[u]=v;
}
}
int main()
{ int u,v;
while(scanf("%d%d",&u,&v))
{ if(u==-1&&v==-1) break;
CLR(indgree,0);
Init();
int num=0,count=0;//结点数,即顶点个个数
if(u==0&&v==0) printf("Case %d is a tree.\n",sum++);
else
{ if(!sign[u]) {sign[u]=1;num++;}//若是没有用到标记用到,且点数+1
if(!sign[v]) {sign[v]=1;num++;}
indgree[v]++;//点v的入度+1
count++;//记录边数
Union(u,v);
while(cin>>u>>v&&u||v)
{ if(!sign[u]) {sign[u]=1;num++;}
if(!sign[v]) {sign[v]=1;num++;}
indgree[v]++;
count++;
Union(u,v);
}
int add=0,flag=0;//add保存父结点个数,即判断树的根结点的个数
for(int i=0;i<MAX;i++)
if(sign[i]&&father[i]==i) add++;
if(add==1) flag=1;//检查是不是只有一个根结点,不是直接输出不是树
if(flag&&num-count==1)//满足只有一个根结点且满足结点数-边数=1
{ for(int i=0;i<MAX;i++)
if(sign[i]&&indgree[i]>1) flag=0;//满足除根结点以外的结点入读只能为1
if(!flag) printf("Case %d is not a tree.\n",sum++);
else printf("Case %d is a tree.\n",sum++);
}
else printf("Case %d is not a tree.\n",sum++);
}
}
return 0;
}
要注意hdu 1325中的结束语句是当两个数都小于0~~不能写都等于-1,否则会TLE的~~
nyist 208(supermarket)题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=208(贪心+并查集)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int MAX=10010;
#define CLR(arr,val) memset(arr,val,sizeof(arr))
int father[MAX],rank[MAX],n;
class Supermarket{
public:
Supermarket(){value=time=0;}
Supermarket(int v,int t):value(v),time(t){}
int Value() const {return value;}
int Time() const {return time;}
friend bool operator<(const Supermarket &s1,const Supermarket &s2)//得加friend
{ return s1.value>s2.value;
}
private:
int value;
int time;
};
class UnionFindSet{
public:
void Init();
int Find(int u)
{ return father[u]==-1?u:Find(father[u]); }
void Union(int u,int v)
{ u=Find(u);
v=Find(v);
father[v]=u;
}
private:
int father[MAX];
int rank[MAX];
};
inline void UnionFindSet::Init()
{ CLR(father,-1);
fill(rank,rank+MAX,1);
}
int main()
{ int value,time;
while(scanf("%d",&n)!=EOF)
{ int sum=0;
vector<Supermarket> v;
UnionFindSet U;
U.Init();
for(int i=0;i<n;i++)
{ scanf("%d%d",&value,&time);
v.push_back(Supermarket(value,time));
}
sort(v.begin(),v.end());
for(vector<Supermarket>::size_type i=0;i<v.size();i++)
{ int u=U.Find(v[i].Time());
if(u)
{ U.Union(u-1,u);
sum+=v[i].Value();
}
}
cout<<sum<<endl;
}
return 0;
}
得用scanf输入~~不然会超时~