计蒜客—— 修建大桥

来源:互联网 发布:迭代器模式 java 编辑:程序博客网 时间:2024/04/27 13:39

蒜头君来到一个由 nn 个小岛组成的世界,岛与岛之间通过修建桥,来让岛上的居民可以去其他的小岛。已知已经修建了 mm 座桥,居民们想让蒜头君帮忙计算,最少还要在修建几座桥,居民们才能去所有的岛。

输入格式

第一行输入俩个数字 nnmm,分别代表岛的个数,和已经修建的桥的个数,岛的编号分别是 1 \ldots n1n。(1 \leq n \leq 10001n10000 \leq m \leq n \times (n-1) / 20mn×(n1)/2)接下来的 mm 行,每行俩个数字,代表这俩个编号的岛之间已经有一座桥了。

输出格式

输出最少还需要修建多少座桥,居民才能去所有的岛。

样例输入

5 41 22 34 51 3

样例输出

1

一开始没看懂,不知道是用图的深度遍历还是广度遍历,后来仔细想了一下,发现先建立一个无向图的邻接表然后再深度遍历这个表,从1这个村庄开始访问,每次访问到一个未标记的村,有效的桥数加1(因为最少的桥数肯定是n-1座,像一维数轴那样排布),
所以最后输出n-1-x即可。(有更简单的方法也求教。)
具体代码如下:
#include<cstring>#include<iostream>using namespace std;const int max_n=100000;const int max_m=100000;struct edge{    int v,next ;}e[max_m];int p[max_n],eid,x=0;void init(){    memset(p,-1,sizeof(p));    eid=0;}void insert(int u,int v){    e[eid].v=v;    e[eid].next=p[u];    p[u]=eid++;}bool vis[max_n];void dfs(int u){   // cout<<"vis"<<u<<endl;    vis[u]=true;    for(int i=p[u];i!=-1;i=e[i].next){        if(!vis[e[i].v]){            x++;            dfs(e[i].v);        }    }}int main(){    int n,m;    cin>>n>>m;    init();    memset(vis,false,sizeof(vis));    for(int i=0;i<m;i++)    {        int a,b;        cin>>a>>b;        insert(a,b);        insert(b,a);    }    for(int i=1;i<=n;i++)        dfs(i);    cout<<n-x-1;}


原创粉丝点击