• Redundant Paths POJ


    无向图概念:(这里的x->y表示x和y之间有一条无向边
    1.桥:对于一个无向图,如果删除某条边后,该图的连通分量增加,则称这条边为桥

    比如1->2->3->4这样一个简单得图一共有3个桥,分别是1->2,2->3,3->4

    1->2->3->4->1 这样就没有桥,因为删除任意一个边,任意两点还可以互相往来(因为是双向边嘛)


    2.割点/割项:对于一个无向图,如果删除某个节点u后,该图的连通分量增加,则节点u为割项或关节点

    1->2->3->4 这样的图有2个割点,分别是2,3

    1->2->3->4->1这样的图也是没有割点的,删除任意一个点其他点还是可以往来的


    3.点-双联通:对于一个连通图,如果任意两点至少存在两条点不重复路径(即在从x走到y,如果删除任意一个其他点还可以从x走到y),
      则称这个图为点双连通(也就是通常说的的双联通) 这样的图没有割点


    4.边-双联通:对于一个连通图,如果任意两点至少存在两条边不重复路径,则称该图为边双连通的

    这样的图没有割边

    题意:

    贝西和牛群被迫从一片标着1..F的牧场走到另一片牧场,他们必须在烂苹果树附近穿过。奶牛现在已经厌倦了经常被迫走一条特定的路,想要建一些新的路,这样它们就可以在任何一对田地之间至少有两条不同的路可选。他们目前在每对字段之间至少有一条路由,并且希望至少有两条路由。

    题解:

    那我们可以把所有割边都消除了就可以了

    我们通过看图可以发现,割边一般是存在在一个点只与其他所有点有且仅有一条无向边

    因为题目上已经保证了任意两点之间至少有一条路,所有我们找到所有这样的点,让它们互相连起来就可以了

    黑边是原图的,红边是添加后使图变成边-双连通图的

    根据上面描述,2,3,4都属于这样的点,我们就需要2条边就可以使它变成双连通图

    根据上面描述,2,3,4,5都属于这样的点,我们就需要2条边就可以使它变成双连通图

     这样的话,任意一个点到达其他点至少有两条路径

    代码1:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<map>
     6 using namespace std;
     7 const int maxn=5010;
     8 int head[maxn],cnt,num,stacks[maxn],top,cut,in[maxn],out[maxn];
     9 struct edge
    10 {
    11     int v,next;
    12 }e[maxn];
    13 int visit[maxn],belong[maxn],dfn[maxn],low[maxn];
    14 void add_edge(int x,int y)
    15 {
    16     e[cnt].v=y;
    17     e[cnt].next=head[x];
    18     head[x]=cnt++;
    19 }
    20 void init()
    21 {
    22     memset(in,0,sizeof(in));
    23     memset(out,0,sizeof(out));
    24     memset(head,-1,sizeof(head));
    25     cnt=num=top=cut=0;
    26 }
    27 void tarjan(int x,int pre)
    28 {
    29     low[x]=dfn[x]=++num;
    30     visit[x]=1;
    31     stacks[top++]=x;
    32     int flag=1;
    33     for(int i=head[x];i!=-1;i=e[i].next)
    34     {
    35         int v=e[i].v;
    36         if(v==pre && flag)
    37         {
    38             flag=0;
    39             continue;
    40         }
    41         if(!dfn[v])
    42         {
    43             tarjan(v,x);
    44             low[x]=min(low[x],low[v]);
    45         }
    46         else if(visit[v])
    47         {
    48             low[x]=min(low[x],dfn[v]);
    49         }
    50     }
    51     if(low[x]==dfn[x])
    52     {
    53         cut++;
    54         int v;
    55         while(true)
    56         {
    57             v=stacks[top-1];
    58             top--;
    59             belong[v]=cut;
    60             visit[v]=0;
    61             if(v==x) break;
    62             //printf("*");
    63         }
    64     }
    65 }
    66 int main()
    67 {
    68     int n,m;
    69     init();
    70     scanf("%d%d",&n,&m);
    71     while(m--)
    72     {
    73         int x,y;
    74         scanf("%d%d",&x,&y);
    75         add_edge(x,y);
    76         add_edge(y,x);
    77     }
    78     tarjan(1,-1);
    79     //printf("**
    ");
    80     for(int i=1;i<=n;++i)
    81     {
    82         for(int j=head[i];j!=-1;j=e[j].next)
    83         {
    84             int v=e[j].v;
    85             if(belong[i]!=belong[v])
    86             {
    87                 in[belong[v]]++;
    88                 out[belong[i]]++;
    89             }
    90         }
    91     }
    92     int ans=0;
    93     for(int i=1;i<=n;++i)
    94     {
    95         if(out[i]==1)
    96             ans++;
    97     }
    98     printf("%d
    ",(ans+1)/2);
    99 }
    View Code

    代码2:

      1 //time 1031MS
      2 
      3 //memory 31340K
      4 
      5 #pragma comment(linker, "/STACK:1024000000,1024000000")
      6 
      7 #include <iostream>
      8 
      9 #include <cstdio>
     10 
     11 #include <cstdlib>
     12 
     13 #include <cstring>
     14 
     15 #define MAXN 300015
     16 
     17 #define MAXM 4000015
     18 
     19 using namespace std;
     20 
     21 struct Edge{
     22 
     23     int v,next;
     24 
     25 }e[MAXM];
     26 
     27 int head[MAXN],en;
     28 
     29 int head2[MAXN],en2;
     30 
     31 int belong[MAXN],dfn[MAXN],low[MAXN],sta[MAXN],top,num,scc;
     32 
     33 int in[MAXN],out[MAXN];
     34 
     35 bool vis[MAXN];
     36 
     37 void init()
     38 
     39 {
     40 
     41     memset(head,-1,sizeof(head));
     42 
     43     memset(vis,0,sizeof(vis));
     44 
     45     en = 0;
     46 
     47     top = 0;
     48 
     49     scc=num = 0;memset(dfn,0,sizeof(dfn));
     50 
     51 }
     52 
     53 void addedge(int u,int v)
     54 
     55 {
     56 
     57     e[en].v = v;
     58 
     59     e[en].next = head[u];
     60 
     61     head[u] = en++;
     62 
     63 }
     64 
     65 //void addedge2(int u,int v)
     66 //
     67 //{
     68 //
     69 //    edge2[en2].v = v;
     70 //
     71 //    edge2[en2].next = head2[u];
     72 //
     73 //    head2[u] = en2++;
     74 //
     75 //}
     76 
     77 void tarjan(int u,int fa)
     78 
     79 {
     80 
     81     dfn[u] = low[u] = ++num;
     82 
     83     sta[++top] = u;
     84 
     85     int cnt=0;
     86 
     87     for(int i = head[u]; i != -1; i = e[i].next)
     88 
     89     {
     90 
     91         int v = e[i].v;
     92 
     93         if(!dfn[v])
     94 
     95         {
     96 
     97             tarjan(v,u);
     98 
     99             low[u] = min(low[u],low[v]);
    100 
    101         }
    102 
    103         else if (fa==v)
    104 
    105         {
    106 
    107             if (cnt) low[u] = min(low[u],dfn[v]);//重边
    108 
    109             cnt++;
    110 
    111         }
    112 
    113         else low[u] = min(low[u],dfn[v]);
    114 
    115     }
    116 
    117     if(dfn[u]==low[u])
    118 
    119     {
    120 
    121         int x;
    122 
    123         scc++;
    124 
    125         do
    126 
    127         {
    128 
    129             x = sta[top--];
    130 
    131             belong[x] = scc;
    132 
    133         }while(x!=u);
    134 
    135     }
    136 
    137 }
    138 
    139 //void build()
    140 //
    141 //{
    142 //
    143 //    en2 = 0;
    144 //
    145 //    memset(head2,-1,sizeof(head2));
    146 //
    147 //    for(int i = 1; i <= n; i++)
    148 //
    149 //    {
    150 //
    151 //        for(int j = head[i]; j!=-1; j = e[j].next)
    152 //
    153 //        {
    154 //
    155 //            int v = e[j].v;
    156 //
    157 //            if(belong[i]!=belong[v])
    158 //
    159 //                addedge2(belong[i],belong[v]);
    160 //
    161 //        }
    162 //
    163 //    }
    164 //
    165 //}
    166 
    167 int ans;
    168 
    169 //int dfs(int u,int p)
    170 //
    171 //{
    172 //
    173 //    int max1=0,max2=0;
    174 //
    175 //    for (int i=head2[u];i!=-1;i=edge2[i].next)
    176 //
    177 //    {
    178 //
    179 //        int v=edge2[i].v;
    180 //
    181 //        if (v==p) continue;
    182 //
    183 //        int tmp=dfs(v,u)+1;
    184 //
    185 //        if (max1<tmp) max2=max1,max1=tmp;
    186 //
    187 //        else if (max2<tmp) max2=tmp;
    188 //
    189 //    }
    190 //
    191 //    ans=max(ans,max1+max2);
    192 //
    193 //    return max1;
    194 //
    195 //}
    196 int main()
    197 {
    198     int n,m;
    199     init();
    200     scanf("%d%d",&n,&m);
    201     while(m--)
    202     {
    203         int x,y;
    204         scanf("%d%d",&x,&y);
    205         addedge(x,y);
    206         addedge(y,x);
    207     }
    208     tarjan(1,-1);
    209     //printf("**
    ");
    210     for(int i=1;i<=n;++i)
    211     {
    212         for(int j=head[i];j!=-1;j=e[j].next)
    213         {
    214             int v=e[j].v;
    215             if(belong[i]!=belong[v])
    216             {
    217                 in[belong[v]]++;
    218                 out[belong[i]]++;
    219             }
    220         }
    221     }
    222     int ans=0;
    223     for(int i=1;i<=n;++i)
    224     {
    225         if(out[i]==1)
    226             ans++;
    227     }
    228     printf("%d
    ",(ans+1)/2);
    229 }
    230 //int main()
    231 //
    232 //{
    233 //
    234 //    //freopen("/home/qitaishui/code/in.txt","r",stdin);
    235 //
    236 //    int u,v;
    237 //
    238 //    while(scanf("%d%d",&n,&m)&&(n+m))
    239 //
    240 //    {
    241 //
    242 //        init();
    243 //
    244 //        //cout<<n<<m<<endl;
    245 //
    246 //        for(int i = 0; i < m; i++)
    247 //
    248 //        {
    249 //
    250 //            scanf("%d%d",&u,&v);
    251 //
    252 //            if (v==u) continue;
    253 //
    254 //            addedge(u,v);
    255 //
    256 //            addedge(v,u);
    257 //
    258 //            //cout<<u<<" "<<v<<endl;
    259 //
    260 //        }
    261 //
    262 //
    263 //
    264 //        tarjan(1,-1);
    265 //
    266 //        build();
    267 //
    268 //        ans=0;
    269 //
    270 //        dfs(1,-1);
    271 //
    272 //        printf("%d
    ",scc-ans-1);
    273 //
    274 //    }
    275 //
    276 //    return 0;
    277 //
    278 //}
    View Code
  • 相关阅读:
    vue的自定义组件和组件传值
    VUE的语法笔记
    Vue 的语法
    about use Vue of methods
    移动端使用下拉加载的简单方法
    深入理解nodejs的next函数。koa的使用 app.params的使用
    ACM输入输出超级外挂(朋友你渴望力量吗)fread版本
    Codeforces 1028C(面积并/思维)
    HDU 2457(AC自动机+dp)
    HDU 2825(AC自动机+状压dp)
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/11664054.html
Copyright © 2020-2023  润新知