UVALive - 5135 Mining Your Own Business

刘汝佳白书上面的一道题目:题意是给定一个联通分量,求出割顶以及双连通分量的个数,并且要求出安放安全井的种类数,也就是每个双连通分量中结点数(除开 割顶)个数相乘,对于有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\n",(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\n", 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\n",(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\n", t, ans1, ans2);
130         t++;
131     }
132     return 0;
133 }
View Code

 

 

你可能感兴趣的:(live)