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?
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(T≤30)
——The number of the testcases.
For each testcase, the first line contains a number n(n≤100) .
Then n+1 lines follow. Each line contains two numbers u,v , which means there is an edge between u and v.
For each testcase, the first line contains a number n(n≤100) .
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;
}