Skip to main content
  1. Posts/

bc #73 B || hdu 5631 Rikka with Graph (并查集判断无向图的连通性)

Note: This article is available in Chinese only. 本文暂无英文版本。 View original

http://acm.hdu.edu.cn/showproblem.php?pid=5631 题意;给出一张n个点n+1(n<=100)条边的无向图,现在删除若干条边(至少一条边),问删完之后图依然联通的方案数。 思路:分析可知,由于只删边,不删点,n个点,最少需要n-1条边才能联通,所以最多删两条边。我们可以暴力枚举删除的两条边(或者一条边) O(n^2)的复杂度完全可以接受。剩下的问题就变成了每次删边之后判断图的连通性。 题解给出的是bfs。。。大概是bfs一遍,然后入队的点数是n就联通? 或者dfs一遍也可以? 也是标记过的点数是n就说明联通? 但是看到排名考前的人都是用到了并查集来判断…比较巧妙。

具体做法是:先把所有的点孤立出来,然后开始添加边,每次union成功(就是添加了一条边)的时候计数器+1,n个点如果能合并n-1次,也就是添加了n-1条有效边(最多也只可能是n-1条,那么说明这n个点之间是联通的。

第一次这样用并查集…憋说话,用心感悟。

  1/* ***********************************************
  2Author :111qqz
  3Created Time :2016年03月03日 星期四 21时11分19秒
  4File Name :code/hdu/5631.cpp
  5************************************************ */
  6
  7#include <cstdio>
  8#include <cstring>
  9#include <iostream>
 10#include <algorithm>
 11#include <vector>
 12#include <queue>
 13#include <set>
 14#include <map>
 15#include <string>
 16#include <cmath>
 17#include <cstdlib>
 18#include <ctime>
 19#define fst first
 20#define sec second
 21#define lson l,m,rt<<1
 22#define rson m+1,r,rt<<1|1
 23#define ms(a,x) memset(a,x,sizeof(a))
 24typedef long long LL;
 25#define pi pair < int ,int >
 26#define MP make_pair
 27
 28using namespace std;
 29const double eps = 1E-8;
 30const int dx4[4]={1,0,0,-1};
 31const int dy4[4]={0,-1,1,0};
 32const int inf = 0x3f3f3f3f;
 33const int N=105;
 34int n;
 35int f[N];
 36bool ban[N];
 37pi edge[N];
 38
 39
 40void init()
 41{
 42    ms(f,0);
 43    for ( int i = 0 ; i < N ; i++) f[i] =  i;
 44}
 45
 46int root ( int x)
 47{
 48    if (f[x]!=x)
 49    f[x]=root(f[x]);
 50    return f[x];
 51}
 52
 53int Union( int x,int y)
 54{
 55    int rootx = root(x);
 56    int rooty = root(y);
 57  //  cout<<"rootx:"<<rootx<<" rooty:"<<rooty<<endl;
 58    if (rootx!=rooty)
 59    {
 60    f[rootx]=rooty;
 61
 62    return 1;
 63    }
 64    return 0;
 65}
 66
 67int solve()       //用并查集判断图连通性。如果是联通图,那么一定会合并(union)n-1次(得到一棵生成树)
 68    //每次合并相当于添加了一条边,而且是不会使得图出现环的边。
 69{
 70    init();  //对于每一种情况,都要初始化一次。
 71
 72    int cnt_merge = 0;
 73
 74    for ( int i = 0 ; i <= n ; i++)
 75    {
 76    if (!ban[i])
 77    {
 78        cnt_merge+=Union(edge[i].fst,edge[i].sec);
 79    }
 80    }
 81    return cnt_merge==n-1;
 82}
 83int main()
 84{
 85    #ifndef  ONLINE_JUDGE
 86    freopen("code/in.txt","r",stdin);
 87  #endif
 88
 89    ios::sync_with_stdio(false);
 90    int T;
 91    cin>>T;
 92    while (T--)
 93    {
 94      //  init();
 95        cin>>n;
 96        for ( int i = 0 ; i <= n ; i++) cin>>edge[i].fst>>edge[i].sec;
 97
 98        ms(ban,false);
 99
100        int ans = 0  ;
101        for ( int i = 0 ; i <= n ; i++)
102        {
103        ban[i] = true;
104        ans +=solve();
105        for ( int j = i+1 ; j <= n ; j++)
106        {
107            ban[j] = true;
108            ans +=solve();
109            ban[j] = false; //回溯
110        //    cout<<"ans:"<<ans<<endl;
111        }
112        ban[i] = false ;//回溯
113
114        }
115        cout<<ans<<endl;
116    }
117
118  #ifndef ONLINE_JUDGE
119  fclose(stdin);
120  #endif
121    return 0;
122}

Related

bzoj 1604: [Usaco2008 Open]Cow Neighborhoods 奶牛的邻居 (曼哈顿距离的转化【拆点】+set+并查集)

http://www.lydsy.com/JudgeOnline/problem.php?id=1604 题意:了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的N(1≤N≤100000)只奶牛,你会发现她们已经结成了几个“群”.每只奶牛在吃草的时候有一个独一无二的位置坐标Xi,Yi(l≤Xi,Yi≤[1..10^9];Xi,Yi∈整数.当满足下列两个条件之一,两只奶牛i和j是属于同一个群的: 1.两只奶牛的曼哈顿距离不超过C(1≤C≤10^9),即lXi - xil+IYi - Yil≤C. 2.两只奶牛有共同的邻居.即,存在一只奶牛k,使i与k,j与k均同属一个群. 给出奶牛们的位置,请计算草原上有多少个牛群,以及最大的牛群里有多少奶牛

hdoj 5606 ||bc #68 div 2 B tree

·2 mins
http://acm.hdu.edu.cn/showproblem.php?pid=5606 题意:一棵树,边权为0或者1,问对于每个点,距离它最近的点(包括自身)的个数是多少。输出将所有点的答案异或后的值。 思路:由于包括自身,自己与自己距离为0,那么最近的点一定也距离为0,所以就是找对于每个点与它相连的边权为0 的点的个数**。建图的时候可以不管边权为1的点。。因为这样的点不会对任何点的答案有贡献。**正解貌似是冰茶几。。我就是dfs搞了下。。找到每一个联通快的点数。。然后把某个联通快的所有点的答案都更新成点的个数。。。

codeforces 22 C. System Administrator

·2 mins
http://codeforces.com/contest/22/problem/C 题意:要求用n个点m条边构造一个不允许有重边的图,满足当去掉点v的时候,剩下的n-1个不联通。如果有答案输出任意,没答案输出-1. 思路:首先如果n个点要联通。。至少有n-1条边,此时为一棵树。但是是不是边越多越好呢?显然是不可以的。满足去掉一个点使得n-1个点不联通的情况为,存在一个点u只和v相连,不和任意任何其他点相连,那么当去掉v点,u点就变成不可到达了。边数最多的情况就是,除了v点以外的n-1个点,每个点的度都是n-2(去掉自身以及u点还有n-2个点),,那么除去u点以外的n-1个点的度数就是(n-1)(n-2),边数则为(n-1)(n-2)/2,再加一条连接u的边,所以图的最大边数为(n-1)*(n-2)/2+1,最小为n-1.

codeforces #333 div 2 C. The Two Routes

·2 mins
http://codeforces.com/problemset/problem/602/C 题意:给出n个城镇,m条双向铁路,对于任意不同的x,y,如果x,y之间没有铁路,那么一定有双向公路。train只能走铁路,bus只能走公路。现在一辆火车和一辆bus同时从1出发,要到达n,处于安全考虑,bus和火车不能同时处在除了n以外的点。bus和train不要求同时到达。任意一段道路的时间花费都是1小时。问最少需要多久使得bus和train都到达n。如果存在某个不能到达,那么输出-1. 思路:n才400.一开始打算先按照rail和road建两个图。这两个图互为补。然后在floyd的时候加以判断。但是马上就发现。。不能同时到达同伙一个点这个条件其实不会影响。。因为按照题意,一定存在一条1到n的路,不是公路就是铁路。那么就让有路的花费1的代价到n,然后剩下的求一个一到n的最短路即可。由于n才400.。最短路怎么搞都行。。我偷懒就用floyd了。

poj 3687 Labeling Balls

http://poj.org/problem?id=3687 题意:给定几个标签球的重量大小关系,求每个球是第几重的(即每个球在所有球的重量中由小到大排名是多少)。 (输出是每个球第几重,而不是几号球比几号球重!)。一开始理解错了QAQ 思路:反向拓扑+优先队列。因为正向不好用。。。所以我们连边的时候由重的指向轻的。。这样最先出队的就是最重的。。和上道题差不多?