zoukankan      html  css  js  c++  java
  • [HNOI2012]矿场搭建【割点Tarjan】

    题目链接

      有M条边,告诉你u、v两点有一条无向边,然后点是所有输入点的最大值,现在问如果有任意一个点被删除了,要保证剩下的点都有办法走到出口,所需要的最少建设的出口通道是几个?并且输出方案数。

      很明显一点,如果某个强连通子图没有割点的话,那么说明这个子图==该联通子图,那么只需要从其中所有的点随便选两个点作为出口点即可,方案数为C(N, 2),需要加的点是2个。

      如果,存在一个强连通子图,它有且只有一个割点,那么需要从它内的V-1个点中(排除那个割点)选一个点作为出口点,如果割的不是割点,那么其余点就可以通过走割点方向走出去,如果是割点的话,那个其余点就走这个点走出去。

      如果存在一个强连通子图,它有多个割点(≥2),那么他就不需要再新建点了,它可以从没有被删除的割点方向找到出路。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cmath>
      4 #include <string>
      5 #include <cstring>
      6 #include <algorithm>
      7 #include <limits>
      8 #include <vector>
      9 #include <stack>
     10 #include <queue>
     11 #include <set>
     12 #include <map>
     13 #include <bitset>
     14 #include <unordered_map>
     15 #include <unordered_set>
     16 #define lowbit(x) ( x&(-x) )
     17 #define pi 3.141592653589793
     18 #define e 2.718281828459045
     19 #define INF 0x3f3f3f3f
     20 #define HalF (l + r)>>1
     21 #define lsn rt<<1
     22 #define rsn rt<<1|1
     23 #define Lson lsn, l, mid
     24 #define Rson rsn, mid+1, r
     25 #define QL Lson, ql, qr
     26 #define QR Rson, ql, qr
     27 #define myself rt, l, r
     28 #define pii pair<int, int>
     29 #define MP(a, b) make_pair(a, b)
     30 using namespace std;
     31 typedef unsigned long long ull;
     32 typedef unsigned int uit;
     33 typedef long long ll;
     34 const int maxN = 1e3 + 7;
     35 int N, M, head[maxN], cnt;
     36 struct Eddge
     37 {
     38     int nex, to;
     39     Eddge(int a=-1, int b=0):nex(a), to(b) {}
     40 }edge[maxN << 1];
     41 bool vis[maxN << 1] = {false};
     42 void addEddge(int u, int v)
     43 {
     44     edge[cnt] = Eddge(head[u], v); vis[cnt] = false;
     45     head[u] = cnt++;
     46 }
     47 inline void _add(int u, int v) { addEddge(u, v); addEddge(v, u); }
     48 int dfn[maxN], low[maxN], tot = 0, Stap[maxN], Stop, Bcnt, Bhave_cut[maxN] = {0};
     49 bool iscut[maxN] = {false};
     50 vector<int> Bt[maxN], V;
     51 void Tarjan(int u, int fa)
     52 {
     53     int child = 0;
     54     V.push_back(u);
     55     dfn[u] = low[u] = ++tot;
     56     Stap[++Stop] = u;
     57     for(int i=head[u], v; ~i; i=edge[i].nex)
     58     {
     59         if(vis[i]) continue;
     60         vis[i] = vis[i ^ 1] = true;
     61         v = edge[i].to;
     62         if(!dfn[v])
     63         {
     64             child++;
     65             Tarjan(v, u);
     66             low[u] = min(low[u], low[v]);
     67             if(low[v] >= dfn[u])
     68             {
     69                 iscut[u] = true;
     70                 int p; Bcnt++; Bt[Bcnt].clear(); Bhave_cut[Bcnt] = 0;
     71                 do
     72                 {
     73                     p = Stap[Stop--];
     74                     Bt[Bcnt].push_back(p);
     75                 } while(p ^ v);
     76                 Bt[Bcnt].push_back(u);
     77             }
     78         }
     79         else low[u] = min(low[u], dfn[v]);
     80     }
     81     if(!fa && child == 1) iscut[u] = false;
     82 }
     83 inline void init()
     84 {
     85     cnt = tot = Bcnt = Stop = 0;
     86     memset(dfn, 0, sizeof(dfn));
     87     memset(iscut, false, sizeof(iscut));
     88     memset(head, -1, sizeof(head));
     89 }
     90 int main()
     91 {
     92     int Cas = 0;
     93     while(scanf("%d", &M) && M)
     94     {
     95         init(); N = 0;
     96         for(int i=1, u, v; i<=M; i++)
     97         {
     98             scanf("%d%d", &u, &v); N = max(N, max(u, v));
     99             _add(u, v);
    100         }
    101         ull ans_num = 0, ans_sum = 1;
    102         for(int i=1, len, cnum; i<=N; i++)
    103         {
    104             if(!dfn[i])
    105             {
    106                 V.clear();
    107                 Bcnt = 0;
    108                 Tarjan(i, 0);
    109                 len = (int)V.size();
    110                 cnum = 0;
    111                 for(int j=0; j<len; j++)
    112                 {
    113                     if(iscut[V[j]]) cnum++;
    114                 }
    115                 if(!cnum)
    116                 {
    117                     ans_num += 2;
    118                     ans_sum *= 1LL * len * (len - 1) / 2;
    119                 }
    120                 else
    121                 {
    122                     for(int j=1; j<=Bcnt; j++)
    123                     {
    124                         for(int v : Bt[j]) if(iscut[v]) Bhave_cut[j]++;
    125                         if(Bhave_cut[j] == 1)
    126                         {
    127                             ans_num++;
    128                             ans_sum *= (Bt[j].size() - 1);
    129                         }
    130                     }
    131                 }
    132             }
    133         }
    134         printf("Case %d: %llu %llu
    ", ++Cas, ans_num, ans_sum);
    135     }
    136     return 0;
    137 }
  • 相关阅读:
    32位二进制IP地址与十进制IP地址互相转换
    在安装AndroidStudio时产生的问题
    Java 数列求和
    Java throws Exception、try、catch
    Java 语句循环
    Oracle OEM
    数据泵Expdp和Impdp
    java查询高斯数据库表某个字段值
    安全测试笔记(未更新完)
    工作笔记
  • 原文地址:https://www.cnblogs.com/WuliWuliiii/p/13814799.html
Copyright © 2011-2022 走看看