• uva 10972 RevolC FaeLoN cdoj 方老师和农场


    //自己写的第一发tarjan

    解:先进行双连通分解并缩点,分解后一定是一颗树,设叶节点个数为n那么答案就是(n+1)/2

    关于双连通分量求解:在跑tarjan时判断每个点连向父节点的边是否是桥,如果是桥的话,该点的后代
    中,未被染色的节点一点构成一个双连通分量,那么将其染色。

    染色完成后依次检查每一条边的两端是
    否为两种不同的颜色,如果是,所对应的颜色的度+1,最后看多少个度为1的节点就知道有多少叶子节点
    也就能得到答案了。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<queue>
      8 #include<vector>
      9 #include<map>
     10 #include<stack>
     11 #include<string>
     12 
     13 using namespace std;
     14 
     15 const int MAXN=100007;
     16 const int MAXM=100007;
     17 
     18 vector<int> G[MAXN];
     19 int n,m,top,cnt1,cnt2;
     20 bool vis[MAXN];
     21 int color[MAXN],dfn[MAXN],low[MAXN];
     22 int stk[MAXN];
     23 int degree[MAXN];
     24 
     25 void tarjan(int now,int fa){
     26     cnt1++;
     27     dfn[now]=low[now]=cnt1;
     28     vis[now]=1;
     29     stk[top++]=now;
     30     int sz=G[now].size();
     31     for (int i=0;i<sz;i++){
     32             if (G[now][i]==fa) continue;
     33             if (!vis[G[now][i]]){
     34                     tarjan(G[now][i],now);
     35                     low[now]=min(low[now],low[G[now][i]]);
     36                     if (low[G[now][i]]>dfn[now]){
     37                             cnt2++;
     38                             while (top>0){
     39                                     color[stk[--top]]=cnt2;
     40                                     if (stk[top]==G[now][i]) break;
     41                             }
     42                     }
     43             }
     44             else{
     45                     low[now]=min(low[now],dfn[G[now][i]]);
     46             }
     47     }
     48 }
     49 
     50 int main(){
     51     while (scanf("%d%d",&n,&m)==2){
     52     cnt1=cnt2=top=0;
     53     memset(vis,0,sizeof(vis));
     54     memset(degree,0,sizeof(degree));
     55     memset(color,0,sizeof(color));
     56     memset(dfn,0,sizeof(dfn));
     57     memset(low,0,sizeof(low));
     58     memset(stk,0,sizeof(stk));
     59     for (int i=1;i<=n;i++){
     60             G[i].clear();
     61     }
     62     for (int i=0;i<m;i++){
     63             int x,y;
     64             scanf("%d%d",&x,&y);
     65             G[x].push_back(y);
     66             G[y].push_back(x);
     67     }
     68     for (int i=1;i<=n;i++){
     69             if (dfn[i]==0) tarjan(i,-1);
     70     }
     71     if (cnt2==1){
     72             printf("0
    ");
     73             continue;
     74     }
     75     for (int i=1;i<=n;i++){
     76             int sz=G[i].size();
     77             for (int j=0;j<sz;j++){
     78                     if (color[i]!=color[G[i][j]]){
     79                             degree[color[i]]++;
     80                     }
     81             }
     82     }
     83     int ans=0;
     84     for (int i=1;i<=cnt2;i++){
     85             if (degree[i]==0) ans+=2;
     86             if (degree[i]==1) ans+=1;
     87     }
     88     printf("%d
    ",(ans+1)/2);
     89     }
     90     return 0;
     91 }
     92 /*
     93 7 7
     94 1 2
     95 2 3
     96 3 4
     97 2 5
     98 4 5
     99 5 6
    100 5 7
    101 
    102 3 3
    103 1 2
    104 2 3
    105 1 3
    106 
    107 
    108 7 5
    109 1 2
    110 2 3
    111 4 5
    112 5 6
    113 5 7
    114 */
  • 相关阅读:
    js根据年份获取某月份有几天
    java 时间转换去杠
    简单Maven Dos命令语句
    Maven命令参数
    Redis学习推荐
    Java中Redis缓存
    oracle新建登录用户sql语句
    ORacle修改表列长度
    jsp利用application统计在线人数的方法
    Oracle之分页查询
  • 原文地址:https://www.cnblogs.com/baby-mouse/p/4550520.html
Copyright © 2020-2023  润新知