【LA】5135 Mining Your Own Business

【算法】点双连通分量

【题解】详见《算法竞赛入门竞赛入门经典训练指南》P318-319

细节在代码中用important标注。

#include<cstdio>
#include<algorithm>
#include<vector>
#include<stack>
#include<cstring>
using namespace std;
const int maxm=50010;
struct edge{int u,v,from;}e[maxm*3];
int first[maxm],iscut[maxm],dfn[maxm],low[maxm],bccno[maxm],bcc_cnt,dfsnum,tot,n,m,kase;
vector<int>bcc[maxm];
stack<int>s;
void insert(int u,int v)
{tot++;e[tot].u=u;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
void tarjan(int x,int fa)
{
    dfn[x]=low[x]=++dfsnum;
    int child=0;
    for(int i=first[x];i;i=e[i].from)
     if(e[i].v!=fa)
      {
          int y=e[i].v;
//          s.push(i);
          if(!dfn[y])
           {
              s.push(i);//
              child++; //important
               tarjan(y,x);
               low[x]=min(low[x],low[y]);
               if(low[y]>=dfn[x])
                {
                    iscut[x]=1;
                    bcc_cnt++;
                    bcc[bcc_cnt].clear();
                    for(;;)
                     {
                         int now=s.top();s.pop();
                         int u=e[now].u,v=e[now].v;
                         if(bccno[u]!=bcc_cnt){bcc[bcc_cnt].push_back(u);bccno[u]=bcc_cnt;}
                         if(bccno[v]!=bcc_cnt){bcc[bcc_cnt].push_back(v);bccno[v]=bcc_cnt;}
//                         printf("%d\n",bcc_cnt);
                         if(u==x&&v==y)break;
                     }
                }
           }
          else if(dfn[y]<dfn[x])s.push(i),low[x]=min(low[x],dfn[y]);//important
      }
    if(fa<0&&child==1)iscut[x]=0;
}
int main()
{
    scanf("%d",&m);
    while(m!=0)
     {
         memset(first,0,sizeof(first));
         n=0;tot=0;bcc_cnt=0;
         for(int i=1;i<=m;i++)
          {
              int u,v;
              scanf("%d%d",&u,&v);
              n=max(n,max(u,v));
              insert(u,v);
              insert(v,u);
          }
         memset(dfn,0,sizeof(dfn));
         memset(low,0,sizeof(low));
         memset(iscut,0,sizeof(iscut));
         memset(bccno,0,sizeof(bccno));
         dfsnum=0;
         while(!s.empty())s.pop();
         for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i,-1);
         long long ans1=0,ans2=1;
         for(int i=1;i<=bcc_cnt;i++)
          {
              int cut_cnt=0;
              for(int j=0;j<bcc[i].size();j++)
               if(iscut[bcc[i][j]])cut_cnt++;
              if(cut_cnt==1)
               {
                   ans1++;
                   ans2*=(long long)(bcc[i].size()-cut_cnt);
               }
          }
         if(bcc_cnt==1)
          {
              ans1=2;
              ans2=bcc[1].size()*(bcc[1].size()-1)/2;
          }
         printf("Case %d: %lld %lld\n",++kase,ans1,ans2);
         scanf("%d",&m);
     }
    return 0;
}

时间: 2024-08-26 09:59:15

【LA】5135 Mining Your Own Business的相关文章

LA 5135 Mining Your Own Business

求出 bcc 后再……根据大白书上的思路即可. 然后我用的是自定义的 stack 类模板: 1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 //#include<stack> 5 #include<stdexcept> 6 #include<algorithm> 7 using namespace std; 8 typedef long long LL; 9 co

UVALive - 5135 Mining Your Own Business(双连通分量)

题目大意:有N个矿井 ,由一些隧道连接起来,现在要修建尽量少的安全通道,使得无论哪里发生事故,所有人均能逃出,求建的最少的安全通道数量和方案数 解题思路:建安全通道的话,肯定不能建在割顶,因为割顶如果崩塌了,割顶所连接的双连通分量内的点就跑不掉了,还得在双连通分量里面再建点(上述为双连通分量内部只有一个割顶的情况),这样不划算,还不如直接在里面建点 如果一个双连通分量的内部割顶有多个的话,那么在这个双连通分量里面就可以不用建安全通道了,因为一个割顶崩塌了,还有其他点可以连向外面,所以,只考虑内部

UVALive 5135 Mining Your Own Business 双连通分量 2011final

题意:n条隧道由一些点连接而成,其中每条隧道链接两个连接点.任意两个连接点之间最多只有一条隧道.任务就是在这些连接点中,安装尽量少的太平井和逃生装置,使得不管哪个连接点倒塌,工人都能从其他太平井逃脱,求最少安装数量和方案. 思路:其实本题就相当于在一张无向图中,涂尽量少的黑点,使得任意删除哪个点,每个连通分量至少有一个黑点.因为不同的连通分量最多只有一个公共点,那一定是割点.可以发现,涂黑割点是不划算的,而且在 一个点-双连通分量中涂黑两个黑点也是不划算的.所以只有当点-双连通分量只有一个割点时

UVALive 5135 Mining Your Own Business

题意: 一些隧道组成矿井  现在要修建尽量少的逃生通道  使得无论哪里发生事故  所有人均能逃出  求方案数 思路: 这道题比较容易联想到割点  因为只有这种点出事矿井才会不连通  那么首先就找出所有割点 分析最少要建几个逃生通道  那当然是每个连通块各一个  因此需要把求出连通块顶点数之积 最后考虑特殊情况  没有割点  那么随便两个地方建就好了  不能建一个  万一就那里出事了呢- 代码: #include<cstdio> #include<cstring> #include&

【算法】图论

[最短路] bool spfa() { memset(vis,0,sizeof(vis)); memset(d,0x3f,sizeof(d)); int head=0,tail=1;q[0]=S;vis[S]=1;d[S]=0; while(head!=tail) { int x=q[head++];if(head>3000)head=0; for(int i=first[x];i;i=e[i].from) if(d[x]+e[i].w<d[e[i].v]) { int y=e[i].v; d

【LA 3641】 Leonardo&#39;s Notebook (置换群)

[题意] 给出26个大写字母组成 字符串B问是否存在一个置换A使得A^2 = B [分析] 置换前面已经说了,做了这题之后有了更深的了解. 再说说置换群.   首先是群. 置换群的元素是置换,运算时是置换的连接. 前面已经说了,每个置换都可以写成互不相交的循环的乘积. 然后分析一下这题. 假设A置换是(a1,a2,a3)(b1,b2,b3,b4)   [这里用循环表示 那么A*A=(a1,a2,a3)(b1,b2,b3,b4)(a1,a2,a3)(b1,b2,b3,b4) 不相交的循环满足交换律

【分享】数据挖掘学习资料免费下载

 Artificial Intelligence - Wiley - Data Mining - Concepts Models Methods and Algorithms - 2003.chm 8.4 MB  IEEE - Finding Patterns in Three Dimensional Graphs Algorithms and Applications to Scientific Data Mining.pdf 561.8 KB  Mining The Web - Discov

SCI&amp;EI 英文PAPER投稿经验【转】

英文投稿的一点经验[转载] From: http://chl033.woku.com/article/2893317.html 1. 首先一定要注意杂志的发表范围, 超出范围的千万别投,要不就是浪费时间;另外,每个杂志都有他们的具体格式要求,一定要按照他们的要求把论文写好,免得浪费时间,前些时候,我的一个同事向一个著名的英文杂志投稿,由于格式问题,人家过两个星期就退回来了,而且说了很多难听的话,说投稿前首先就应该看清楚他们的格式要求:2. 论文写作一定要言简意赅,特别是摘要,引言和结论部分,特别

[转]机器学习和深度学习资料汇总【01】

本文转自:http://blog.csdn.net/sinat_34707539/article/details/52105681 <Brief History of Machine Learning> 介绍:这是一篇介绍机器学习历史的文章,介绍很全面,从感知机.神经网络.决策树.SVM.Adaboost到随机森林.Deep Learning. <Deep Learning in Neural Networks: An Overview> 介绍:这是瑞士人工智能实验室Jurgen