• POJ3177(Redundant Paths) or POJ3352(Road Construction)


    POJ3177

    POJ3352

     把这两个题写到一起,是因为这两题完全一样,用下面的代码两个题都可以AC。题目大意是给一个无向连通图,求添加最少边数使原图变成双连通图。由于是第一次写双连通图的缩点,所以WA了5次,在WA到AC的过程中,发现的错误如下:1、深度优先数没有初始化;2、深度优先数初始化错误;3、桥的判断有误;4、输入数据有重边,使用邻接表存储没有跳过重边。下面写一下这题的主要思路,用数组dfn保存各个结点的访问顺序(深度优先数),数组low[k]保存结点k及其子结点通过回边能到达的所有结点的最小深度优先数(下面简称最小深度优先数)。若子节点的最小深度优先数大于父结点的最小深度优先数,则连接父子结点的边为桥,否则该边不是桥。程序中使用了并查集来合并属于同一个双连通分量的所有结点(简称缩点),下面将简单证明这样做的正确性。要证明能够使用并查集来合并,只需证明点与点之间的双连通关系是等价关系即可。已知点a与点b双连通(a到b至少有两条不同路径),点b与点c双连通,求证点a与点c双连通。分两种情况讨论:1、点c在a到b的路径上,则结论显然成立;2、点c不在a到b的路径上,则路径ab与路径bc连接即可得到路径ac,同理可得路径ca。以上就证明了点与点双连通是等价关系。用并查集缩点后,得到的是一棵树,将一棵树通过加边的到双连通图需加最少边数为(叶子结点数目+1)/2。

    View Code
      1 #include <stdio.h>
    2 #include <string.h>
    3 #include <stdlib.h>
    4 #define N 5001
    5 #define MIN(a,b) ((a)<(b)?(a):(b))
    6 #define SET(a,b) (memset(a,b,sizeof(a)))
    7 struct node
    8 {
    9 int v;
    10 struct node *next;
    11 };
    12 struct node *list[N];
    13 int p[N],n,m;
    14 int dfn[N],low[N],father[N],id[N],d[N],t;
    15 char vis[N],flag[N][N];
    16 void addEdge(int u,int v)
    17 {
    18 struct node *p=(struct node *)malloc(sizeof(struct node));
    19 p->v=v,p->next=list[u],list[u]=p;
    20 }
    21 void make_set()
    22 {
    23 int i;
    24 for(i=0;i<n;i++) p[i]=i;
    25 }
    26 int find_set(int i)
    27 {
    28 if(i!=p[i]) p[i]=find_set(p[i]);
    29 return p[i];
    30 }
    31 void union_set(int i,int j)
    32 {
    33 i=find_set(i),j=find_set(j);
    34 if(i==j) return;
    35 p[j]=i;
    36 }
    37 void init()
    38 {
    39 make_set();
    40 SET(vis,0),SET(father,-1);
    41 dfn[0]=low[0]=vis[0]=t=1;
    42 }
    43 void dfs_con2(int u)
    44 {
    45 int v;
    46 struct node *p;
    47 for(p=list[u];p;p=p->next)
    48 {
    49 v=p->v;
    50 if(vis[v])
    51 {
    52 if(father[u]!=v) low[u]=MIN(low[u],dfn[v]);
    53 }
    54 else
    55 {
    56 vis[v]=1,t++;
    57 father[v]=u;
    58 dfn[v]=low[v]=t;
    59 dfs_con2(v);
    60 low[u]=MIN(low[u],low[v]);
    61 if(dfn[u]>=low[v]) union_set(u,v);
    62 }
    63 }
    64 }
    65 int main()
    66 {
    67 int i,j,a,b,cnt,d1;
    68 struct node *q;
    69 while(scanf("%d%d",&n,&m)!=EOF)
    70 {
    71 SET(flag,0);
    72 for(i=0;i<m;i++)
    73 {
    74 scanf("%d%d",&a,&b),a--,b--;
    75 if(flag[a][b] || flag[b][a]) continue;
    76 flag[a][b]=flag[b][a]=1;
    77 addEdge(a,b),addEdge(b,a);
    78 }
    79 init();
    80 dfs_con2(0);
    81 SET(id,-1);
    82 for(i=0,cnt=0;i<n;i++)
    83 {
    84 j=find_set(i);
    85 if(id[j]==-1) id[j]=cnt++;
    86 id[i]=id[j];
    87 }
    88 SET(d,0);
    89 for(i=0;i<n;i++)
    90 {
    91 for(q=list[i];q;q=q->next)
    92 {
    93 j=q->v;
    94 if(j<i) continue;
    95 if(id[i]!=id[j]) d[id[i]]++,d[id[j]]++;
    96 }
    97 }
    98 for(i=0,d1=0;i<cnt;i++) d1+=(d[i]==1)?1:0;
    99 printf("%d\n",(d1+1)/2);
    100 for(i=0;i<n;i++)
    101 {
    102 for(q=list[i];q;)
    103 {
    104 list[i]=q->next,free(q),q=list[i];
    105 }
    106 }
    107 }
    108 return 0;
    109 }
  • 相关阅读:
    装饰模式(Decorator Pattern)
    适配器模式(Adapter Pattern)
    组合模式
    单例的两种模式
    抽象工厂模式(Abstract Factory Pattern)
    工厂方法模式
    桥接模式
    原型模式(Prototype Pattern)
    建造者模式(Builder Pattern)
    解决使用tomcat服务器发布web项目时出现URL中文乱码的问题
  • 原文地址:https://www.cnblogs.com/algorithms/p/2432135.html
Copyright © 2020-2023  润新知