zoukankan      html  css  js  c++  java
  • UVALive

    刘汝佳白书上面的一道题目:题意是给定一个联通分量,求出割顶以及双连通分量的个数,并且要求出安放安全井的种类数,也就是每个双连通分量中结点数(除开 割顶)个数相乘,对于有2个及以上割顶的双连通分量可以不用安放安全井。如果整个图就是一个双连通分量,那么需要安放两个安全井,种类数是n*(n-1)/2.

    代码来自刘汝佳白书:

      1 #include <iostream>
      2 #include <sstream>
      3 #include <cstdio>
      4 #include <climits>
      5 #include <cstring>
      6 #include <cstdlib>
      7 #include <string>
      8 #include <stack>
      9 #include <map>
     10 #include <cmath>
     11 #include <vector>
     12 #include <queue>
     13 #include <algorithm>
     14 #define esp 1e-6
     15 #define pi acos(-1.0)
     16 #define pb push_back
     17 #define mp(a, b) make_pair((a), (b))
     18 #define in  freopen("in.txt", "r", stdin);
     19 #define out freopen("out.txt", "w", stdout);
     20 #define print(a) printf("%d
    ",(a));
     21 #define bug puts("********))))))");
     22 #define stop  system("pause");
     23 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
     24 #define pragma comment(linker, "/STACK:102400000, 102400000")
     25 #define inf 0x0f0f0f0f
     26 
     27 
     28 using namespace std;
     29 typedef long long  LL;
     30 typedef vector<int> VI;
     31 typedef pair<int, int> pii;
     32 typedef vector<pii,int> VII;
     33 typedef vector<int>:: iterator IT;
     34 const int maxn =  50010;
     35 struct Edge{
     36 int u, v;
     37 Edge(int u, int v):u(u), v(v){}
     38 };
     39 int pre[maxn], low[maxn], bccno[maxn], iscut[maxn], bcc_cnt, dfs_clock;
     40 VI g[maxn], bcc[maxn];
     41 stack<Edge> S;
     42 int dfs(int u, int fa)
     43 {
     44     int lowu = pre[u] = ++dfs_clock;
     45     int child = 0;
     46     for(int i = 0; i < g[u].size(); i++)
     47     {
     48         int v = g[u][i]; Edge e = Edge(u, v);
     49         if(!pre[v])
     50         {
     51             S.push(e);
     52             child++;
     53             int lowv = dfs(v, u);
     54             lowu = min(lowu, lowv);
     55             if(lowv >= pre[u])
     56             {
     57                 iscut[u] = 1;
     58                 bcc_cnt++; bcc[bcc_cnt].clear();
     59                 for(;;)
     60                 {
     61                     Edge x = S.top(); S.pop();
     62                     if(bccno[x.u] != bcc_cnt) {bccno[x.u] = bcc_cnt; bcc[bcc_cnt].pb(x.u);}
     63                     if(bccno[x.v] != bcc_cnt) {bccno[x.v] = bcc_cnt; bcc[bcc_cnt].pb(x.v);}
     64                     if(x.u == u && x.v == v) break;
     65                 }
     66             }
     67         }
     68         else if(pre[v] < pre[u] && v!= fa)
     69         {
     70             S.push(e);
     71             lowu = min(lowu, pre[v]);
     72         }
     73     }
     74     if(child == 1 && fa < 0) iscut[u] = 0;
     75     return low[u] = lowu;
     76 }
     77 void find_bcc(int n)
     78 {
     79     memset(iscut, 0, sizeof(iscut));
     80     memset(pre, 0, sizeof(pre));
     81     memset(bccno, 0, sizeof(bccno));
     82 
     83     dfs_clock = bcc_cnt = 0;
     84     for(int i = 0; i < n; i++)
     85         if(!pre[i]) dfs(i, -1);
     86 }
     87 int kase;
     88 void solve(int n)
     89 {
     90     find_bcc(n);
     91     LL ans1 = 0, ans2 = 1;
     92     for(int i = 1; i <= bcc_cnt; i++)
     93     {
     94         int cut_cnt = 0;
     95         for(int j = 0; j < bcc[i].size(); j++)
     96             if(iscut[bcc[i][j]]) cut_cnt++;
     97         if(cut_cnt == 1)
     98             ans1++, ans2 *= (LL)(bcc[i].size() - cut_cnt);
     99     }
    100     if(bcc_cnt == 1)
    101     {
    102         ans1 = 2, ans2 = (LL)(n-1)*n/2;
    103     }
    104     printf("Case %d: %I64d %I64d
    ", kase, ans1, ans2);
    105 }
    106 int main(void)
    107 {
    108     int m;
    109     while(scanf("%d", &m), m)
    110     {
    111         kase++;
    112         for(int i = 0; i < maxn; i++)
    113             g[i].clear();
    114         int mxn = 0;
    115         while(m--)
    116         {
    117             int u, v;
    118             scanf("%d%d", &u, &v);
    119             mxn = max(mxn, max(u, v));
    120             u--, v--;
    121             g[u].pb(v), g[v].pb(u);
    122         }
    123         solve(mxn);
    124     }
    125     return 0;
    126 }
    View Code

     此题的另一种解法是先求出割顶,然后从非割顶的点dfs一遍,注意这个过程中不能经过割顶,统计每次dfs中遇到割顶的数目,如果为1,则更新答案。同样注意割顶为0的情况。

    代码:

      1 #include <iostream>
      2 #include <sstream>
      3 #include <cstdio>
      4 #include <climits>
      5 #include <cstring>
      6 #include <cstdlib>
      7 #include <string>
      8 #include <stack>
      9 #include <map>
     10 #include <cmath>
     11 #include <vector>
     12 #include <queue>
     13 #include <algorithm>
     14 #define esp 1e-6
     15 #define pi acos(-1.0)
     16 #define pb push_back
     17 #define mp(a, b) make_pair((a), (b))
     18 #define in  freopen("in.txt", "r", stdin);
     19 #define out freopen("out.txt", "w", stdout);
     20 #define print(a) printf("%d
    ",(a));
     21 #define bug puts("********))))))");
     22 #define stop  system("pause");
     23 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
     24 #define inf 0x0f0f0f0f
     25 #pragma comment(linker, "/STACK:102400000,102400000")
     26 
     27 using namespace std;
     28 typedef long long  LL;
     29 typedef vector<int> VI;
     30 typedef pair<int, int> pii;
     31 typedef vector<pii,int> VII;
     32 typedef vector<int>:: iterator IT;
     33 const int maxn = 50000 + 10;
     34 int pre[maxn], low[maxn], iscut[maxn], dfs_clock;
     35 VI g[maxn], cut;
     36 int n;
     37 LL ans1, ans2, cut_cnt;
     38 int dfs(int u, int fa)
     39 {
     40     int lowu = pre[u] = ++dfs_clock;
     41     int child = 0;
     42     for(int i = 0; i < g[u].size(); i++)
     43     {
     44         int v = g[u][i];
     45         if(!pre[v])
     46         {
     47             child++;
     48             int lowv = dfs(v, u);
     49             lowu = min(lowu, lowv);
     50             if(lowv >= pre[u])
     51             {
     52                 iscut[u] = 1;
     53             }
     54         }
     55         else if(pre[v] < pre[u] && v != fa)
     56         {
     57             lowu = min(lowu, pre[v]);
     58         }
     59     }
     60     if(child == 1 && fa < 0)
     61         iscut[u] = 0;
     62     return low[u] = lowu;
     63 }
     64 void find_bcc(int n)
     65 {
     66     memset(pre, 0, sizeof(pre));
     67     memset(iscut, 0, sizeof(iscut));
     68     dfs_clock = 0;
     69     for(int  i = 0; i < n; i++)
     70         if(!pre[i])
     71             dfs(i, -1);
     72 }
     73 int cnt;
     74 void dfs1(int u)
     75 {
     76     cnt++;
     77     pre[u] = 1;
     78     for(int i = 0; i < g[u].size(); i++)
     79     {
     80         int v = g[u][i];
     81         if(!pre[v])
     82         {
     83             if(iscut[v]) cut_cnt++, cnt++, pre[v] = 1, cut.pb(v);
     84             else dfs1(v);
     85         }
     86     }
     87 }
     88 void solve(int n)
     89 {
     90     cut.clear();
     91     cut_cnt= 0;
     92     memset(pre, 0, sizeof(pre));
     93     for(int i = 0; i < n; i++)
     94         if(iscut[i]) cut_cnt++;
     95 
     96     if(cut_cnt == 0) ans1 = 2, ans2 = (LL)n*(n-1)/2;
     97     else for(int i = 0; i < n; i++)
     98             if(!pre[i] && !iscut[i])
     99             {
    100                 cut_cnt = cnt = 0;
    101                 dfs1(i);
    102                 for(int i = 0; i  < cut.size(); i++)
    103                     pre[cut[i]] = 0;
    104                 cut.clear();
    105                 if(cut_cnt == 1)
    106                     ans1++, ans2 *= (LL)(cnt-1);
    107             }
    108 }
    109 int main(void)
    110 {
    111     int m, t = 1;
    112     while(scanf("%d", &m), m)
    113     {
    114         n = 0;
    115         ans1 = 0, ans2 = 1;
    116         for(int i = 0; i < maxn; i++)
    117             g[i].clear();
    118         while(m--)
    119         {
    120             int u, v;
    121             scanf("%d%d", &u, &v);
    122             n = max(n, max(u, v));
    123             u--, v--;
    124             g[u].pb(v);
    125             g[v].pb(u);
    126         }
    127         find_bcc(n);
    128         solve(n);
    129         printf("Case %d: %I64d %I64d
    ", t, ans1, ans2);
    130         t++;
    131     }
    132     return 0;
    133 }
    View Code
  • 相关阅读:
    Window安装Redis并设置为开机启动
    大佬为你揭秘微信支付的系统架构,你想知道的都在这里了
    想要设计自己的微服务?看这篇文章就对了
    破局人工智能:构建AI,与腾讯云一起探索语音应用场景
    巧用机器学习定位云服务器故障
    重磅发布 | 黑镜调查:深渊背后的真相之「DDoS 威胁与黑灰产业调查报告」
    5分钟内看懂机器学习和深度学习的区别
    如何防范和应对Redis勒索,腾讯云教你出招
    Redis勒索事件爆发,如何避免从删库到跑路?
    作为一个编程新手,我再也不怕Flink迷了我的眼!
  • 原文地址:https://www.cnblogs.com/rootial/p/3335880.html
Copyright © 2011-2022 走看看