zoukankan      html  css  js  c++  java
  • P3225 [HNOI2012]矿场搭建

    https://www.luogu.org/problemnew/show/P3225

    用Tarjan跑出割点,然后DFS搜索所有的联通快

    计算每一个联通快中的割点数目

    分类讨论:

    如果没有割点

    至少需要建立两个出口

    从任意非割点的地方选择两个点建立

    如果这个分组只有一个割点

    只需要在分组内设立一个出口

    可以设立在任意一个非割点的地方

    如果有两个及以上个割点,则无需建立,可以直接到达其他联通块

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<algorithm>
      5 using namespace std;
      6 inline int read(){
      7     int sum=0,x=1;
      8     char ch=getchar();
      9     while(ch<'0'||ch>'9'){
     10         if(ch=='-')
     11             x=0;
     12         ch=getchar();
     13     }
     14     while(ch>='0'&&ch<='9')
     15         sum=(sum<<1)+(sum<<3)+(ch^48),ch=getchar();
     16     return x?sum:-sum;
     17 }
     18 inline void write(int x){
     19     if(x<0)
     20         putchar('-'),x=-x;
     21     if(x>9)
     22         write(x/10);
     23     putchar(x%10+'0');
     24 }
     25 typedef long long ll;
     26 const int M=520;
     27 ll ans1,ans2;
     28 int n,m;
     29 ll tot,cnt,root,child,liantong,vnum,cutnum;
     30 struct node{
     31     int v,nextt;
     32 }e[M*M];
     33 int vis[M],dfn[M],low[M],head[M],cut[M]; 
     34 void tarjan(int u,int f){
     35     dfn[u]=low[u]=++cnt;
     36     for(int i=head[u];~i;i=e[i].nextt){
     37         int v=e[i].v;
     38         if(!dfn[v]){
     39             tarjan(v,u);
     40             low[u]=min(low[u],low[v]);
     41             if(low[v]>=dfn[u]){
     42                 if(u!=root)
     43                     cut[u]=true;
     44                 else
     45                     child++;
     46             }
     47         }
     48         else if(v!=f) 
     49             low[u]=min(low[u],dfn[v]);
     50     }
     51 }
     52 void dfs(int u){
     53     vis[u]=liantong;
     54     vnum++;
     55     for(int i=head[u];~i;i=e[i].nextt){
     56         int v=e[i].v;
     57         if(cut[v]&&vis[v]!=liantong){
     58             vis[v]=liantong;
     59             cutnum++;
     60         }
     61         if(!vis[v])
     62             dfs(v);
     63     }
     64 }
     65 void addedge(int u,int v){
     66     e[tot].v=v;
     67     e[tot].nextt=head[u];
     68     head[u]=tot++;
     69 }
     70 void init(){
     71     memset(head,-1,sizeof(head));
     72     tot=0;
     73     cnt=0;
     74     ans1=0;
     75     ans2=1;
     76     vnum=cutnum=0;
     77     liantong=0;
     78     n=0;
     79     memset(vis,0,sizeof(vis));
     80     memset(cut,0,sizeof(cut));
     81     memset(dfn,0,sizeof(dfn));
     82     memset(low,0,sizeof(low));
     83 }
     84 int main(){
     85     int t=1;
     86     while(cin>>m){
     87         if(m==0)
     88             break;
     89         init();
     90         
     91         while(m--){
     92             int u,v;
     93             cin>>u>>v;
     94             addedge(u,v);
     95             addedge(v,u);
     96             n=max(u,max(n,v));
     97         }
     98         
     99         for(int i=1;i<=n;i++){
    100             if(!dfn[i]){
    101                 child=0,root=i;
    102                 tarjan(i,i);
    103                 if(child>=2)
    104                     cut[i]=true;
    105             }
    106         }
    107         for(int i=1;i<=n;i++){
    108             if(!vis[i]&&!cut[i]){
    109                 ++liantong;
    110                 vnum=0,cutnum=0;
    111                 dfs(i);
    112                 //cout<<"!!"<<vnum<<endl;
    113                 if(cutnum==0){
    114                     ans1+=2;
    115                     ans2*=vnum*(vnum-1)/2;
    116                 }
    117                 else if(cutnum==1){
    118                     ans1+=1;
    119                     ans2*=vnum;
    120                 }
    121             }
    122         }
    123         printf("Case %d: %lld %lld
    ",t++,ans1,ans2);
    124     }
    125     return 0;
    126 }
    View Code
  • 相关阅读:
    103. 二叉树的锯齿形层次遍历
    102. 二叉树的层次遍历
    94. 二叉树的中序遍历
    Redis和数据库 数据同步问题
    203. 移除链表元素
    19. 删除链表的倒数第N个节点
    237. 删除链表中的节点
    141. 环形链表
    2. 两数相加
    143. 重排链表
  • 原文地址:https://www.cnblogs.com/starve/p/11055405.html
Copyright © 2011-2022 走看看