POJ:2914 Minimum Cut(暴力枚举并查集)

4 篇文章 0 订阅
4 篇文章 0 订阅

Rikka with Graph

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1042    Accepted Submission(s): 501


Problem Description
As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

Yuta has a non-direct graph with n vertices and n+1 edges. Rikka can choose some of the edges (at least one) and delete them from the graph.

Yuta wants to know the number of the ways to choose the edges in order to make the remaining graph connected.

It is too difficult for Rikka. Can you help her?
 

Input
The first line contains a number  T(T30) ——The number of the testcases.

For each testcase, the first line contains a number  n(n100) .

Then n+1 lines follow. Each line contains two numbers  u,v  , which means there is an edge between u and v.
 

Output
For each testcase, print a single number.
 

Sample Input
  
  
1 3 1 2 2 3 3 1 1 3
 

Sample Output
  
  
9
 

Source
 

Recommend
hujie

题目大意:给你一个n表示有1~n ,n个点,接下来有n+1行,每行含数字a、b,表示a、b两点相连。问有多少种策略,从这些边集中抽出若干条边,使得剩下的点仍相连。
解题思路:比如有k个点,那么至少得有k-1条边才能使得所有点相连,这道题给了n+1条边,n个点,那么取出边集的策略只能是从中取出一条边或两条边,这样暴力枚举下取出一条边的所有情况,取出两条边的所有情况,如果取出后树的个数仍是1,那么情况数+1.
代码如下:
#include <cstdio>
int n;
int pre[110];
struct node
{
	int s,e;
}en[110];//每条边的两条端点 
void chushihua()//初始化父节点 
{
	for(int i=1;i<=n;i++)
	{
		pre[i]=i;
	}
}
int find(int x)//找祖宗+路径压缩 
{
	int r=x;
	while(r!=pre[r])
	{
		r=pre[r];
	}
	int i=x,j;
	while(i!=r)
	{
		j=pre[i];
		pre[i]=r;
		i=j;
	}
	return r;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		int sum=0;
		for(int i=1;i<=n+1;i++)
		{
			scanf("%d%d",&en[i].s,&en[i].e);
		}
		for(int i=1;i<=n+1;i++)//删去一条边 
		{
			chushihua();//别忘了初始化 
			for(int j=1;j<=n+1;j++)
			{
				if(j==i)
				continue;//取出第i条边,将剩下的边连接起来 
				int fx=find(en[j].s);
				int fy=find(en[j].e);
				if(fx!=fy)
				{
					pre[fx]=fy;
				}
			}
			int rootnum=0;
			for(int i=1;i<=n;i++)//判断树的个数 
			{
				if(pre[i]==i)
				rootnum++;
			}
			if(rootnum==1)
			sum++;
		}
		for(int i=1; i<=n; i++)
		{
			for(int j=i+1; j<=n+1; j++)//组合去掉的两条边 
			{
				chushihua();//别忘了初始化 
				for(int k=1; k<=n+1; k++)//删掉两条边 
				{
					if(k == i||k == j)//删掉第i条和第j条,连接剩下的边 
					continue;
					int fx=find(en[k].s);
					int fy=find(en[k].e);
					if(fx!=fy)
					{
						pre[fx]=fy;
					}
				}
				int rootnum= 0;
				for(int k=1; k<=n; k++)//判断树的个数 
				{
					if(pre[k]==k)
					rootnum++;
				}
				if(rootnum==1)
				sum++;
			}
		}
		printf("%d\n",sum);
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值