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
  • 相关阅读:
    android 多行文本显示的textView
    FastJson 打Release 包解析失败
    Android 颜色透明度换算
    Android Stadio 导入moudle 不显示
    Android onConfigurationChanged 收不到回调
    如何在TortoiseGit中使用ssh-keygen生成的key
    Android 判断屏幕方向一个大坑
    requestLayout 无效
    Android stadio Switch repository Android stadio切换仓库
    Windows usb设备正在使用中
  • 原文地址:https://www.cnblogs.com/yzcstc/p/4089533.html
Copyright © 2011-2022 走看看