BestCoder Round #73 (div.2)(B)并查集

来源:互联网 发布:ios常见多线程编程 编辑:程序博客网 时间:2024/05/30 22:59

Rikka with Graph

 
 Accepts: 123
 
 Submissions: 525
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
问题描述
众所周知,萌萌哒六花不擅长数学,所以勇太给了她一些数学问题做练习,其中有一道是这样的:给出一张 nn 个点 n+1n+1 条边的无向图,你可以选择一些边(至少一条)删除。现在勇太想知道有多少种方案使得删除之后图依然联通。当然,这个问题对于萌萌哒六花来说实在是太难了,你可以帮帮她吗?
输入描述
第一行一个整数表示数据组数 T(T \leq 30)T(T30)。每组数据的第一行是一个整数 n(n \leq 100)n(n100)。接下来 n+1n+1 行每行两个整数 u,vu,v 表示图中的一条边。
输出描述
对每组数据输出一行一个整数表示答案。
输入样例
131 22 33 11 3
输出样例
9




题解:他只给你(N+1)条边,而形成一个联通图至少需要(N-1)条边,那么多出来的2条边只需要双重循环枚举删除2条边的各种可能性就好了,使用并查集维护点的关系,这里如果出现多棵树的根,那么就一定不是联通图,这里还是说一下,枚举从自己开始枚举,就是删除一条边的情况与删除2条边的情况




#include<iostream>#include<cstdio>#include<algorithm>#include<vector>#include<utility>using namespace std;vector<pair<int,int>>v;#define N 105int fa[N];int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}void unio(int x,int y){x=find(x);y=find(y);if(x!=y)fa[x]=y;}int solve(int x,int y,int n){for(int i=1;i<=n;i++){fa[i]=i;}for(int i=0;i<=n;i++){if(i==x||i==y)continue;unio(v[i].first,v[i].second);}int num=0;for(int i=1;i<=n;i++){if(fa[i]==i)num++;}return num>1?0:1;}int main(){#ifdef CDZSCfreopen("i.txt","r",stdin);#endifint n,y,x,t;scanf("%d",&t);while(t--){int ans=0;v.clear();scanf("%d",&n);for(int i=0;i<=n;i++){scanf("%d%d",&x,&y);v.push_back(make_pair(x,y));}for(int i=0;i<=n;i++){for(int j=i;j<=n;j++){ans+=solve(i,j,n);}}printf("%d\n",ans);}return 0;}











0 0
原创粉丝点击