推荐一个图论基本概念的传送门
http://hi.baidu.com/lydrainbowcat/item/f8a5ac223e092b52c28d591c
做法就是缩点,缩点后会变成个树 然后记录树中度数为1的节点数res
还有一个坑就是有重边,一开始就wa在这了,我直接就用map做了。。
poj3352和这个一样的,就是不用判断重边
这是一个定理咧,自己画画也能明白。。。
# include <iostream> // 妈蛋 有重边
# include <stdio.h>
# include <string.h>
# include <map>
using namespace std;
const int N=5005;
int head[N],low[N],degree[N];
map<int,int> M;
int tot,ti;
struct node
{
int to,next;
}e[1000000];
void add(int s,int u){
e[tot].to=u;
e[tot].next=head[s];
head[s]=tot++;
}
void tarjan(int p,int u)
{
int i;
low[u]=ti++;
for(i=head[u]; i; i=e[i].next)
{
int k=e[i].to;
if(k==p) continue;
if(low[k]==0) tarjan(u,k);
//printf("@@@u=%d l=%d k=%d l=%d\n",u,low[u],k,low[k]);
low[u]=min(low[u],low[k]);
}
}
int main ()
{
int n,m,i,j,k;
while(scanf("%d%d",&n,&m)!=EOF)
{
int a,b;
tot=ti=1;
M.clear();
memset(head,0,sizeof(head));
memset(low,0,sizeof(low));
memset(degree,0,sizeof(degree));
while(m--)
{
scanf("%d%d",&a,&b);
if(!M[a*10000+b]&&!M[a+b*10000]){
add(a,b);
add(b,a);
M[a*10000+b]=M[a+b*10000]=1;
}
}
tarjan(1,1);
for(i=1; i<=n; i++)
{
//printf("##%d %d\n",i,low[i]);
for(j=head[i]; j; j=e[j].next)
{
k=e[j].to;
//printf("##%d %d\n",k,low[k]);
if(low[i]!=low[k]) degree[low[i]]++;
}
}
int res=0;
for(i=1; i<=ti; i++)
{
if(degree[i]==1) res++;
}
printf("%d\n",(res+1)/2);
}
}