poj--3352

这是一道基础的关于图连通分量的基础题目。

值得注意的是这个题目用到了缩点的思想
所谓的缩点其实是将无向图中的点按low值分一下类:

low值相同的点其实是处于同一个连通分支的。这样我们就

可以通过low值求得图的连通分支的个数了,并且可以将每一个连通分支
看成一个"点"。这就是所谓的缩点了 

代码如下:


#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

#define MaxSize 10100

int pre[MaxSize],low[MaxSize],ans[MaxSize];
int dfs_clock,n,m; 
vector<int>map[MaxSize];

int dfs(int u,int fa)
{
	 int lowu=pre[u]=++dfs_clock;
	 int child=0;
	 int k=map[u].size();
	 for(int i=0;i<k;i++)
	 {
	 	 int v=map[u][i];
	 	 if(!pre[v])
	 	 {
	 	 	  child++;
	 	 	  int lowv=dfs(v,u);
	 	 	  lowu=min(lowu,lowv);
	 	 }
	 	 else if(pre[v]<pre[u]&&v!=fa)
		      lowu=min(lowu,pre[v]);
	 } 
	 low[u]=lowu;
	 return lowu;
}

void Create()
{
	 int i,j,k1,k2;
	 for(i=1;i<=n;i++)
	     map[i].clear();
	 for(i=0;i<m;i++)
	 {
	 	 scanf("%d%d",&k1,&k2);
	 	 map[k1].push_back(k2);
	 	 map[k2].push_back(k1);
	 } 
}

void Init()
{
	 memset(pre,0,sizeof(pre));
	 memset(ans,0,sizeof(ans));
	 dfs_clock=0;
}

int Solve()
{  //如何求得每个缩点的度:
    //对于图上每一个点,其必然属于一个缩点;考虑两个直接
	 //相连的点,如果它们的low值不同,就意味着它们属于不同
	  //的连通分支,可以同时将它们所对的缩点的度加1
	  //下面的代码是依次考察一个顶点的所有边,然后统计这个顶点所在缩点的度 
	 int i,j,k,cnt=0;
	 for(i=1;i<=n;i++)
	 {
	 	k=map[i].size();
	    for(j=0;j<k;j++)
		{
			  int v=map[i][j];
			  if(low[i]!=low[v])
			       ans[low[i]]++;    //统计i所在连通分支"缩点"后的度 
		} 
    }
	for(i=1;i<=n;i++)  //统计度为1缩点数目 
	   if(ans[i]==1)
	       cnt++;
    return (cnt+1)/2;  
}
 
int main()
{
   int Case=0;
   while(scanf("%d%d",&n,&m)!=EOF)
   {
       Create();
       Init();
       dfs(1,-1);
       int ans=Solve();
       printf("%d\n",ans);
   }
 return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值