//定义DFN(u)为节点u搜索的次序编号(时间戳)。Low(u)为u或者u的子树能够追溯到的最早的栈中的节点的次序号。
/*
poj3177
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string.h>
using namespace std;
const int N=5005;
const int M=100005;
struct Edge{
int v,next;
}edge[2*M];
int head[N],low[N],dfn[N],belong[N],degree[N],sta[N];
bool vis[N];
int index,cnt,top,scc;
void addedge(int u,int v)
{
edge[index].v=v;
edge[index].next=head[u];
head[u]=index++;
}
void Tarjan(int u,int fa)
{
int i,v;
low[u]=dfn[u]=++cnt;
sta[++top]=u;
vis[u]=true;
for(int i=head[u];i!=-1;i=edge[i].next){
v=edge[i].v;
if(i==(fa^1))continue;
if(!dfn[v]){
Tarjan(v,i);
low[u]=min(low[u],low[v]);
}
else if(vis[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]){
scc++;
while(1){
v=sta[top--];
vis[v]=false;
belong[v]=scc;
if(v==u)break;
}
}
}
int main()
{
int m,n,u,v,i,j;
cin>>n>>m;
index=top=scc=0;
memset(head,-1,sizeof(head));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(vis,false,sizeof(vis));
memset(degree,0,sizeof(degree));
for(int i=0;i<m;i++){
cin>>u>>v;
addedge(u,v);
addedge(v,u);
}
for(i=1;i<=n;i++){}
if(!dfn[i])Tarjan(1,-1);
for(i=1;i<=n;i++){
for(j=head[i];j!=-1;j=edge[j].next){
v=edge[j].v;
if(belong[i]!=belong[v])
degree[belong[i]]++;
}
}
int sum=0;
for(int i=1;i<=n;i++)
if(degree[i]==1)sum++;
cout<<(sum+1)/2<<endl;
return 0;
}
*/
//poj3352
/*
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<string.h>
using namespace std;
const int N=5005;
const int M=100005;
struct Edge{
int v,next;
}edge[2*M];
int head[N],low[N],dfn[N],belong[N],degree[N],sta[N];
bool vis[N];
int index,cnt,top,scc;
void addedge(int u,int v)
{
edge[index].v=v;
edge[index].next=head[u];
head[u]=index++;
}
void Tarjan(int u,int fa)
{
int i,v;
low[u]=dfn[u]=++cnt;
sta[++top]=u;
vis[u]=true;
for(int i=head[u];i!=-1;i=edge[i].next){
v=edge[i].v;
if(i==(fa^1))continue;
if(!dfn[v]){
Tarjan(v,i);
low[u]=min(low[u],low[v]);
}
else if(vis[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]){
scc++;
while(1){
v=sta[top--];
vis[v]=false;
belong[v]=scc;
if(v==u)break;
}
}
}
int main()
{
int m,n,u,v,i,j;
cin>>n>>m;
index=top=scc=0;
memset(head,-1,sizeof(head));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(vis,false,sizeof(vis));
memset(degree,0,sizeof(degree));
for(int i=0;i<m;i++){
cin>>u>>v;
addedge(u,v);
addedge(v,u);
}
for(i=1;i<=n;i++){}
if(!dfn[i])Tarjan(1,-1);
for(i=1;i<=n;i++){
for(j=head[i];j!=-1;j=edge[j].next){
v=edge[j].v;
if(belong[i]!=belong[v])
degree[belong[i]]++;
}
}
int sum=0;
for(int i=1;i<=n;i++){
if(degree[i]==1)sum++;
}
cout<<(sum+1)/2<<endl;
return 0;
}
*/
//poj1236
/*
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string.h>
#include<string>
#include<vector>
#include<stack>
using namespace std;
const int N=105;
vector<int> G[N];
int head[N],dfn[N],low[N],in[N],out[N];
int belong[N];
bool vis[N];
stack<int>sta;
int index,cnt,top,scc;
void Tarjan(int u)
{
int i,v;
low[u]=dfn[u]=++cnt;
sta.push(u);
vis[u]=true;
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
scc++;
while(true){
int x=sta.top();sta.pop();
vis[x]=false;
belong[x]=scc;
if(x==u)break;
}
}
}
int main()
{
int n;
scc=0;
memset(head,-1,sizeof(head));
memset(belong,0,sizeof(belong));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
memset(vis,false,sizeof(false));
for(int i=0;i<N;i++)
G[i].clear();
cin>>n;
for(int i=1;i<=n;i++){
int v;
while(cin>>v){
if(v==0)break;
G[i].push_back(v);
}
}
for(int i=1;i<=n;i++){
if(!dfn[i])Tarjan(i);
}
if(scc==1){
cout<<1<<endl<<0<<endl;
return 0;
}
for(int i=1;i<=n;i++){
for(int j=0;j<G[i].size();j++){
int v=G[i][j];
if(belong[i]!=belong[v]){
out[belong[i]]++;
in[belong[v]]++;
}
}
}
int ans1=0,ans2=0;
for(int i=1;i<=scc;i++){
if(in[i]==0)ans1++;
if(out[i]==0)ans2++;
}
cout<<ans1<<endl<<max(ans2,ans1)<<endl;
return 0;
}
*/
//poj2186
/*
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string.h>
#include<vector>
using namespace std;
const int N=10005;
const int M=50010;
vector<int>G[N];
int scc,index,cnt,top;
int belong[N],fa[N],out[N],dfn[N],low[N],sta[N];
bool vis[N];
int sum[N];
int Sum;
int n,m;
int ans=0;
int find(int x)
{
if(x==fa[x])return x;
return fa[x]=find(fa[x]);
}
void Union(int u,int v)
{
if(find(u)==find(v))return;
u=find(u),v=find(v);
fa[u]=v;
Sum--;
}
void Tarjan(int u)
{
vis[u]=true;
low[u]=dfn[u]=++cnt;
sta[++top]=u;
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]){
scc++;
while(true){
int v=sta[top--];
vis[v]=false;
belong[v]=scc;
sum[scc]++;
if(v==u)break;
}
}
}
int main()
{
cin>>n>>m;
Sum=n;
memset(out,0,sizeof(out));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(sum,0,sizeof(sum));
memset(vis,false,sizeof(vis));
for(int i=0;i<N;i++)
fa[i]=i,G[i].clear();
cnt=0,scc=0,top=0;
for(int i=0;i<m;i++){
int u,v;
cin>>u>>v;
G[u].push_back(v);
Union(u,v);
}
if(Sum!=1){
ans=0;
}
else{
for(int i=1;i<=n;i++)
if(!dfn[i])Tarjan(i);
for(int i=1;i<=n;i++){
for(int j=0;j<G[i].size();j++){
int v=G[i][j];
if(belong[i]!=belong[v]){
out[belong[i]]++;
}
}
}
int Count=0;
for(int i=1;i<=scc;i++){
if(out[i]==0){
Count++;
ans=sum[i];
}
}
if(Count>1)ans=0;
}
cout<<ans<<endl;
return 0;
}
*/