UVALive 5135 Mining Your Own Bussinesstarjan点双

Posted dream-maker-yk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVALive 5135 Mining Your Own Bussinesstarjan点双相关的知识,希望对你有一定的参考价值。

LINK1

LINK2


题目大意

给你一个无向连通图,让你给一些点染上黑色,需要满足染色之后,断开任意一个节点,要满足任意一个联通块中剩下的节点中至少有一个黑点

思路

一开始想的是把每一个点双联通分量都把除了割点的size乘上

然后发现随手卡掉

然后发现一下性质

首先所有相邻点双联通分量一定有公共的割点

如果一个双联通分量里面只包含了一个割点,那么如果断掉这个割点那么这个双联通分量就被孤立了

所以这样的双联通分量至少选择一个点

然后如果一个双联通分量有大于等于两个割点,就算一个被割掉了另外一边至少连接着1个只有一个割点的点双联通分量

那么就很容易做了

特判一下如果整张图都是一个双联通分量那么就是任意选两个点就可以了


//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
//typename
typedef long long ll;
//convenient for
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
//inf of different typename
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
//fast read and write
template <typename T>
void Read(T &x) {
  bool w = 1;x = 0;
  char c = getchar();
  while (!isdigit(c) && c != '-') c = getchar();
  if (c == '-') w = 0, c = getchar();
  while (isdigit(c)) {
    x = (x<<1) + (x<<3) + c -'0';
    c = getchar();
  }
  if (!w) x = -x;
}
template <typename T>
void Write(T x) {
  if (x < 0) {
    putchar('-');
    x = -x;
  }
  if (x > 9) Write(x / 10);
  putchar(x % 10 + '0');
}
//----------------------------------------------
typedef pair<int, int> pi;
#define fi first
#define se second
const int N = 5e4 + 10;
struct Edge {
  int v, nxt;
} E[N << 1];
stack<pi > st;
int head[N], tot = 0, ind = 0, cnt_bcc = 0;
int n, m, dfn[N], low[N], siz[N], bel[N];
bool iscut[N];
vector<int> g[N];
void init() {
  fu(i, 1, N - 1) dfn[i] = low[i] = bel[i] = head[i] = siz[i] = 0, iscut[i] = 0;
  tot = ind = cnt_bcc = 0;
}
void add(int u, int v) {
  E[++tot] = (Edge) {v, head[u]};
  head[u] = tot;
}
void tarjan(int u, int fa) {
  dfn[u] = low[u] = ++ind;
  int num = 0;
  for (int i = head[u]; i; i = E[i].nxt) {
    int v = E[i].v;
    if (v == fa) continue;
    if (!dfn[v]) {
      st.push(pi(u, v));
      ++num;
      tarjan(v, u);
      low[u] = min(low[u], low[v]);
      if (low[v] >= dfn[u]) {
        iscut[u] = 1;
        g[++cnt_bcc].clear();
        pi now;
        do {
          now = st.top(); st.pop();
          if (bel[now.fi] != cnt_bcc) {
            g[cnt_bcc].push_back(now.fi);
            bel[now.fi] = cnt_bcc;
          } 
          if (bel[now.se] != cnt_bcc) {
            g[cnt_bcc].push_back(now.se);
            bel[now.se] = cnt_bcc;
          }
        } while (now.fi != u || now.se != v);
      }
    } else low[u] = min(low[u], dfn[v]);
  }
  if (num < 2 && !fa) iscut[u] = 0;
}
void solve() {
  n = 0;
  init();
  fu(i, 1, m) {
    int u, v;
    Read(u), Read(v);
    add(u, v);
    add(v, u);
    n = max(n, max(u, v));
  }
  tarjan(1, 0);
  if (cnt_bcc == 1) {
    Write(2), putchar(' ');
    Write(ll(n) * ll(n - 1) / 2), putchar('
');
  } else {
    ll ans1 = 0, ans2 = 1;
    fu(i, 1, cnt_bcc) {
      int cntnow = 0;
      fv(j, g[i])
        if (iscut[g[i][j]]) ++cntnow;
      if (cntnow == 1) 
        ++ans1, ans2 *= (ll) g[i].size() - 1;
    }
    Write(ans1), putchar(' ');
    Write(ans2), putchar('
');
  }
}
int main() {
#ifdef dream_maker
  freopen("input.txt", "r", stdin);
#endif
  int id = 0;
  while (1) {
    Read(m);
    if (!m) return 0;
    printf("Case %d: ", ++id);
    solve();
  }
  return 0;
}

以上是关于UVALive 5135 Mining Your Own Bussinesstarjan点双的主要内容,如果未能解决你的问题,请参考以下文章

LA5135 Mining Your Own Business

UVA5135 Mining Your Own Business ( 无向图双连通分量)

UVALive - 3530:Martian Mining

UVA 1108 - Mining Your Own Business

LA 5135 井下矿工(点—双连通分量模板题)

BK: Data mining, Chapter 2 - getting to know your data