zoukankan      html  css  js  c++  java
  • HDU 3844 Mining Your Own Business(割点,经典)

    题意:

      给出一个连通图,要求将某些点涂黑,使得无论哪个点(包括相关的边)撤掉后能够成功使得剩下的所有点能够到达任意一个涂黑的点,颜料不多,涂黑的点越少越好,并输出要涂几个点和有多少种涂法。

     

    思路:

      要使得任意撤掉一个点都能使其他点能够到达黑点,那么点双连通分量能保证这点,那么就在同个点双连通分量内涂黑1个点。但是每个【点双连通分量】都涂吗?太浪费颜料了,那就缩点成树,只需要涂叶子即可,那就找度为1的缩点。但是种数呢?叶子内的点除了割点外都是可以涂黑的,因为如果黑色割点被撤掉,那么叶子中的其他点怎么办?所以不能涂割点,每个黑点有【叶子中的点数-1】种涂法,所有黑店的涂法相乘为第2个结果。

      特殊情况,因为给的是连通图且至少有2个点,那么还可能会出现没有割点的情况(仅1个点双连通分量),那就直接涂黑两个,以防一个黑点被撤掉。

      此题出现的连续的点可能多达10万个,DFS就会爆栈。在C++下可以手动开栈,G++下的还不清楚怎么开。

      1 #pragma comment(linker,"/STACK:102400000,102400000")//开栈
      2 //#include <bits/stdc++.h>
      3 #include <iostream>
      4 #include <cstdio>
      5 #include <cstring>
      6 #include <algorithm>
      7 #include <vector>
      8 #include <unordered_map>
      9 #include <stack>
     10 #define LL long long
     11 #define pii pair<int,int>
     12 using namespace std;
     13 const int N=100000+5;
     14 const int INF=0x7f7f7f7f;
     15 int up;
     16 int low[N], dfn[N];
     17 bool iscut[N];
     18 int dfn_clock, bcc_cnt, bcc_no[N];
     19 unordered_map<int,int> mapp;
     20 stack< pii >  stac;
     21 vector<int> bcc[N], vect[N];
     22 
     23 void DFS(int x, int far)//tarjan
     24 {
     25     dfn[x]=low[x]=++dfn_clock;
     26 
     27     int chd=0;
     28     for(int i=0; i<vect[x].size(); i++)
     29     {
     30         int t=vect[x][i];
     31         if(!dfn[t])
     32         {
     33             chd++;
     34             stac.push(make_pair(x,t));
     35             DFS(t,x);
     36             low[x]=min( low[x], low[t]);
     37             if(low[t]>=dfn[x])
     38             {
     39                 iscut[x]=true;    //需要标记割点
     40                 bcc[++bcc_cnt].clear();
     41                 while(true)
     42                 {
     43                     int a=stac.top().first;
     44                     int b=stac.top().second;
     45                     stac.pop();
     46                     if(bcc_no[a]!=bcc_cnt)
     47                     {
     48                         bcc[bcc_cnt].push_back(a);
     49                         bcc_no[a]=bcc_cnt;
     50                     }
     51                     if(bcc_no[b]!=bcc_cnt)
     52                     {
     53                         bcc[bcc_cnt].push_back(b);
     54                         bcc_no[b]=bcc_cnt;
     55                     }
     56                     if(a==x&&b==t)    break;
     57                 }
     58             }
     59         }
     60         else if( dfn[t]<dfn[x] && t!=far)
     61         {
     62             stac.push(make_pair(x,t));
     63             low[x]=min(low[x],dfn[t]);
     64         }
     65     }
     66     if(chd==1&&far==0)    iscut[x]=false;        //
     67 }
     68 
     69 void find_bcc(int Case)
     70 {
     71     memset(low,0,sizeof(low));
     72     memset(dfn,0,sizeof(dfn));
     73     memset(iscut,0,sizeof(iscut));
     74     memset(bcc_no,0,sizeof(bcc_no));
     75 
     76     dfn_clock=bcc_cnt=0;
     77     for(int i=1; i<=up; i++)    if(!dfn[i])    DFS(i,0);   //深搜
     78     LL ans1=0,ans2=1;
     79 
     80     for(int i=1; i<=bcc_cnt; i++)    //统计度为多少
     81     {
     82         int cnt=0;
     83         for(int j=0; j<bcc[i].size(); j++)    if(iscut[bcc[i][j] ])    cnt++;    //有割点就统计连通分量i的度。
     84         if(cnt==1)    ans1++, ans2*=bcc[i].size()-1;
     85     }
     86     if(bcc_cnt==1)    ans1=2,ans2=(LL)bcc[1].size()*(bcc[1].size()-1)/2;
     87     printf("Case %d: %lld %lld
    ", Case, ans1, ans2);
     88 }
     89 
     90 
     91 int main()
     92 {
     93     freopen("input.txt", "r", stdin);
     94     int a, b, n, j=0;
     95     while(scanf("%d",&n), n)
     96     {
     97         mapp.clear();
     98         for(int i=1; i<N; i++)    vect[i].clear();
     99         up=0;
    100         for(int i=0; i<n; i++)
    101         {
    102             scanf("%d%d",&a,&b);
    103             if(!mapp[a])    mapp[a]=++up;
    104             if(!mapp[b])    mapp[b]=++up;//点号缩小为连续
    105 
    106             vect[mapp[a]].push_back(mapp[b]);
    107             vect[mapp[b]].push_back(mapp[a]);
    108         }
    109         find_bcc(++j);
    110     }
    111     return 0;
    112 }
    AC代码
  • 相关阅读:
    Leetcode Spiral Matrix
    Leetcode Sqrt(x)
    Leetcode Pow(x,n)
    Leetcode Rotate Image
    Leetcode Multiply Strings
    Leetcode Length of Last Word
    Topcoder SRM 626 DIV2 SumOfPower
    Topcoder SRM 626 DIV2 FixedDiceGameDiv2
    Leetcode Largest Rectangle in Histogram
    Leetcode Set Matrix Zeroes
  • 原文地址:https://www.cnblogs.com/xcw0754/p/4626277.html
Copyright © 2011-2022 走看看