zoukankan      html  css  js  c++  java
  • [poi2007] biu

    题意:给定一个图,点n<=105,边m<=106,现在求它的补图有多少个联通分量。。

    思路:很容易想到并查集,但是补图边太多了。。

            于是只能优化掉一些多余的边。。

           具体做法是用队列优化。。

          刚开始把所有没被连接的点用一个链表连接起来,那么选取一个未扩展得点u,就可以吧链表分成两个,一个就是跟他补图有边的,一个是没边的。。

         并把有边的跟他连接起来。。删除链表。。并放入队列。。

         这样每个点进入队列一次,每条边被访问2次。。时间复杂度为O(n+m)

    code:

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #include<cmath>
      6 #include<algorithm>
      7 #include<string>
      8 #include<map>
      9 #include<set>
     10 #include<vector>
     11 #include<queue>
     12 #include<stack>
     13 #include<ctime>
     14 #define repf(i, a, b) for (int i = (a); i <= (b); ++i)
     15 #define repd(i, a, b) for (int i = (a); i >= (b); --i)
     16 #define M0(x)  memset(x, 0, sizeof(x))
     17 #define Inf  0x7fffffff
     18 #define MP make_pair
     19 #define PB push_back
     20 #define eps 1e-8
     21 #define pi acos(-1.0)
     22 using namespace std;
     23 const int maxn = 120000;
     24 const int maxm = 4200000;
     25 struct edge{
     26       int v, next;
     27 } e[maxm];
     28 struct node{
     29       node *x, *y;
     30 } n1[maxn], n2[maxn], *list[2], *d[2], tr, *null = &tr;
     31 int fa[maxn], last[maxn], tot, n, m;
     32 
     33 void add(const int& u, const int& v){
     34      e[tot] = (edge){v, last[u]}, last[u] = tot++;
     35 }
     36 
     37 void init(){
     38      memset(last, -1, sizeof(last));
     39      int u, v;
     40      for (int i = 0; i < m; ++i){
     41            scanf("%d%d", &u, &v);   
     42            add(u, v), add(v, u);
     43      }     
     44 }
     45 
     46 int sz[maxn], inlist[maxn];
     47 int find(int k){
     48     return fa[k] == k ? k : fa[k] = find(fa[k]); 
     49 }
     50 
     51 void delnode(node *it){
     52      it->x->y = it->y, it->y->x = it->x;
     53      it->x = it->y = null;
     54 }
     55 
     56 void addnode(node *list, node *it){
     57      it->x = list, it->y = list->y;
     58      list->y->x = it, list->y = it;
     59 }
     60 
     61 void clear(int c){
     62      node *uu;
     63      for (node *it = list[c]; it != null;){
     64             uu = it->y;
     65             it->x = it->y = null;
     66             it = uu;
     67      }
     68 }
     69 
     70 void solve(){
     71      M0(n1), M0(n2), M0(inlist);
     72      list[0] = n1 + n + 1, list[1] = n2 + n + 1;
     73      node *it, *uu;
     74      list[0]->x = list[0]->y = null, list[1]->x = list[1]->y = null;
     75      d[0] = n1, d[1] = n2;
     76      int c = 0, u, v;
     77      for (int i = 1; i <= n; ++i) addnode(list[c], d[c] + i), inlist[i] = 1;
     78      for (int i = 1; i <= n; ++i) fa[i] = i;
     79      queue<int> q;
     80      while (list[c]->y != null){
     81          u = list[c]->y - d[c];
     82          q.push(u);
     83          while (!q.empty()){
     84              int s = c ^ 1;
     85              u = q.front(), q.pop();
     86              clear(s);
     87              for (int p = last[u]; ~p; p = e[p].next){
     88                   v = e[p].v;
     89                   if (!inlist[v]) continue;
     90                   delnode(d[c] + v);
     91                   addnode(list[s], d[s] + v);
     92              }
     93              int fu = find(u), fv;
     94              for (it = list[c]->y; it != null; it = it->y){
     95                   v = it - d[c];
     96                   if (!inlist[v]) continue;
     97                   fv = find(v);
     98                   if (fu != fv) fa[fv] = fu;    
     99                   inlist[v] = 0, q.push(v);
    100              }
    101              c = s;
    102          }
    103      }
    104      M0(sz);
    105      for (int i = 1; i <= n; ++i)
    106          ++sz[find(i)];
    107      vector<int> ans;
    108      for (int i = 1; i <= n; ++i) if (sz[i])
    109           ans.push_back(sz[i]);
    110      sort(ans.begin(), ans.end());
    111      printf("%d
    ", (int)ans.size());
    112      for (int i = 0; i < (int)ans.size(); ++i)
    113           i == ans.size()-1 ? printf("%d
    ", ans[i]) : printf("%d ", ans[i]);
    114      
    115 }
    116 
    117 int main(){
    118 //    freopen("a.in", "r", stdin);
    119 //    freopen("a.out", "w", stdout);
    120     while (scanf("%d%d", &n, &m) != EOF){
    121            init();
    122            solve();
    123     }
    124     return 0;
    125 }
    View Code
  • 相关阅读:
    topcoder srm 681 div1
    topcoder srm 683 div1
    topcoder srm 684 div1
    topcoder srm 715 div1
    topcoder srm 685 div1
    topcoder srm 687 div1
    topcoder srm 688 div1
    topcoder srm 689 div1
    topcoder srm 686 div1
    topcoder srm 690 div1 -3
  • 原文地址:https://www.cnblogs.com/yzcstc/p/4089533.html
Copyright © 2011-2022 走看看