• Warm up HDU


    题意:给出n个点和m条边的无向图,存在重边,问加一条边以后,剩下的桥的数量最少为多少。

    题解:

    你把这个无向图缩点后会得到一个只由桥来连接的图(可以说这个图中的所有边都是桥,相当于一棵树),然后我们只需要找出来这棵树的最大直径(即相距最远的两个点)。然后我们可以把得到的这条链的首尾两端连起来,因为这样减少的桥最多。把所有桥减去这条链上的桥就是答案

    找树的直径有两种方法,一种树形dp,一种两次dfs算法。时间复杂度都是O(n)

    先说dfs:

    实现:随意选取一个点作为我们的起点x,找到以x为起点的和它是最远距离的另一个端点y,然后再以y为起点找到和它是最远距离的另一个端点z,这个y->z就是树的最大直径

    本题代码1就是采用的这种解法

    再说树形dp:

    缺点:无法找到它的直径具体路径

    优点:只需一遍遍历

    实现:

     1 //选取任意结点为根遍历树,设dis[i]:表示结点i为根的子树结点最远距离。
     2 //则有:
     3 //u为根的子树结点最远距离dis[u]=max(dis[u],dis[u]+W(u-v)) v是u的子节点
     4 //最后直径即为根结点的两个最远距离之和
     5 int dis[maxn],len=0;
     6 void DP(int u,int pre)
     7 {
     8     dis[u]=0;   //初始为0
     9     for(int i=head[u];i!=-1;i=e[i].next)
    10     {
    11         int v=e[i].v,w=e[i].w;
    12         if(v==pre)
    13             continue;
    14         DP(v,u);
    15         len=max(len,dis[u]+dis[v]+w);  //更新直径
    16         dis[u]=max(dis[u],dis[v]+w);
    17     }
    18 }

    代码1:

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<iostream>
      4 #include<algorithm>
      5 #include<map>
      6 #include<vector>
      7 using namespace std;
      8 const int maxn=200005;
      9 vector<int>w[maxn];
     10 int head[maxn],cnt,num,stacks[maxn],top,cut,in[maxn],out[maxn],pos,ci;
     11 struct edge
     12 {
     13     int v,nnn;
     14 } e[2000005];
     15 int visit[maxn],belong[maxn],dfn[maxn],low[maxn];
     16 void add_edge(int x,int y)
     17 {
     18     e[cnt].v=y;
     19     e[cnt].nnn=head[x];
     20     head[x]=cnt++;
     21 }
     22 void init()
     23 {
     24     memset(low,0,sizeof(low)); //这里忘记初赋值了,卧槽
     25     memset(dfn,0,sizeof(dfn));
     26     memset(head,-1,sizeof(head));
     27     cnt=num=top=cut=ci=0;
     28     pos=-1;
     29 }
     30 void tarjan(int x,int pre)
     31 {
     32     low[x]=dfn[x]=++num;
     33     visit[x]=1;
     34     stacks[top++]=x;
     35     int flag=1;
     36     for(int i=head[x]; i!=-1; i=e[i].nnn)
     37     {
     38         int v=e[i].v;
     39         if(v==pre && flag)
     40         {
     41             flag=0;
     42             continue;
     43         }
     44         if(!dfn[v])
     45         {
     46             tarjan(v,x);
     47             low[x]=min(low[x],low[v]);
     48         }
     49         else if(visit[v])
     50         {
     51             low[x]=min(low[x],dfn[v]);
     52         }
     53     }
     54     if(low[x]==dfn[x])
     55     {
     56         cut++;
     57         int v;
     58         while(true)
     59         {
     60             v=stacks[top-1];
     61             top--;
     62             belong[v]=cut;
     63             visit[v]=0;
     64             if(v==x) break;
     65             //printf("*");
     66         }
     67     }
     68 }
     69 void dfs(int x,int t)
     70 {
     71     if(ci<t)
     72     {
     73         ci=t;
     74         pos=x;
     75     }
     76     visit[x]=1;
     77     int len=w[x].size();
     78     for(int i=0;i<len;++i)
     79     {
     80         int v=w[x][i];
     81         if(visit[v]) continue;
     82         dfs(v,t+1);
     83     }
     84 }
     85 int main()
     86 {
     87     int n,m;
     88     while(~scanf("%d%d",&n,&m) && (n+m))
     89     {
     90         init();
     91         while(m--)
     92         {
     93             int x,y;
     94             scanf("%d%d",&x,&y);
     95             add_edge(x,y);
     96             add_edge(y,x);
     97         }
     98         tarjan(1,-1);
     99         for(int i=1;i<=cut;i++)
    100             w[i].clear();
    101         for(int i=1;i<=n;++i)
    102         {
    103             for(int j=head[i];j!=-1;j=e[j].nnn)
    104             {
    105                 int v=e[j].v;
    106                 int fx=belong[i];
    107                 int fy=belong[v];
    108                 if(fx!=fy)
    109                 {
    110                     w[fx].push_back(fy);
    111                     w[fy].push_back(fx);
    112                 }
    113             }
    114         }
    115         memset(visit,0,sizeof(visit));
    116         dfs(1,0);
    117         memset(visit,0,sizeof(visit));
    118         ci=0;
    119         dfs(pos,0);
    120         printf("%d
    ",cut-ci-1);
    121     }
    122     return 0;
    123 }
    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,nnn;
     24 
     25 }e[MAXM],edge2[MAXM];
     26 
     27 int head[MAXN],en;
     28 
     29 int head2[MAXN],en2;
     30 
     31 int belong[MAXN],dfn[MAXN],low[MAXN],stacks[MAXN],top,num,scc;
     32 
     33 int n,m;
     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].nnn = 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].nnn = head2[u];
     72 
     73     head2[u] = en2++;
     74 
     75 }
     76 
     77 //void tarjan(int u,int fa)  //这个tarjan算法也是可以用的
     78 //
     79 //{
     80 //
     81 //    dfn[u] = low[u] = ++num;
     82 //
     83 //    stacks[++top] = u;
     84 //
     85 //    int cnt=0;
     86 //
     87 //    for(int i = head[u]; i != -1; i = e[i].nnn)
     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 = stacks[top--];
    130 //
    131 //            belong[x] = scc;
    132 //
    133 //        }while(x!=u);
    134 //
    135 //    }
    136 //
    137 //}
    138 void tarjan(int x,int pre)
    139 {
    140     low[x]=dfn[x]=++num;
    141     vis[x]=1;
    142     stacks[top++]=x;
    143     int flag=1;
    144     for(int i=head[x];i!=-1;i=e[i].nnn)
    145     {
    146         int v=e[i].v;
    147         if(v==pre && flag)
    148         {
    149             flag=0;
    150             continue;
    151         }
    152         if(!dfn[v])
    153         {
    154             tarjan(v,x);
    155             low[x]=min(low[x],low[v]);
    156         }
    157         else if(vis[v])
    158         {
    159             low[x]=min(low[x],dfn[v]);
    160         }
    161     }
    162     if(low[x]==dfn[x])
    163     {
    164         scc++;
    165         int v;
    166         while(true)
    167         {
    168             v=stacks[top-1];
    169             top--;
    170             belong[v]=scc;
    171             vis[v]=0;
    172             if(v==x) break;
    173             //printf("*");
    174         }
    175     }
    176 }
    177 void build()
    178 
    179 {
    180 
    181     en2 = 0;
    182 
    183     memset(head2,-1,sizeof(head2));
    184 
    185     for(int i = 1; i <= n; i++)
    186 
    187     {
    188 
    189         for(int j = head[i]; j!=-1; j = e[j].nnn)
    190 
    191         {
    192 
    193             int v = e[j].v;
    194 
    195             if(belong[i]!=belong[v])
    196 
    197                 addedge2(belong[i],belong[v]);
    198 
    199         }
    200 
    201     }
    202 
    203 }
    204 
    205 int ans;
    206 
    207 int dfs(int u,int p)
    208 
    209 {
    210 
    211     int max1=0,max2=0;
    212 
    213     for (int i=head2[u];i!=-1;i=edge2[i].nnn)
    214 
    215     {
    216 
    217         int v=edge2[i].v;
    218 
    219         if (v==p) continue;
    220 
    221         int tmp=dfs(v,u)+1;
    222 
    223         if (max1<tmp) max2=max1,max1=tmp;
    224 
    225         else if (max2<tmp) max2=tmp;
    226 
    227     }
    228 
    229     ans=max(ans,max1+max2);
    230 
    231     return max1;
    232 
    233 }
    234 
    235 int main()
    236 
    237 {
    238 
    239     //freopen("/home/qitaishui/code/in.txt","r",stdin);
    240 
    241     int u,v;
    242 
    243     while(scanf("%d%d",&n,&m)&&(n+m))
    244 
    245     {
    246 
    247         init();
    248 
    249         //cout<<n<<m<<endl;
    250 
    251         for(int i = 0; i < m; i++)
    252 
    253         {
    254 
    255             scanf("%d%d",&u,&v);
    256 
    257             if (v==u) continue;
    258 
    259             addedge(u,v);
    260 
    261             addedge(v,u);
    262 
    263             //cout<<u<<" "<<v<<endl;
    264 
    265         }
    266 
    267 
    268 
    269         tarjan(1,-1);
    270 
    271         build();
    272 
    273         ans=0;
    274 
    275         dfs(1,-1);
    276 
    277         printf("%d
    ",scc-ans-1);
    278 
    279     }
    280 
    281     return 0;
    282 
    283 }
    View Code
  • 相关阅读:
    【摄影】延时摄影
    【sas sql proc】统计
    【分析模板】excel or sas
    JavaScript的方法和技巧
    好书推荐
    七招制胜ASP.NET应用程序开发
    .Net中使用带返回值的存储过程(VB代码)
    ASP.NET 2.0构建动态导航的Web应用程序(TreeView和Menu )
    简单查询和联合查询两方面介绍SQL查询语句
    数字金额大小写转换之存储过程
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/11665442.html
Copyright © 2020-2023  润新知