sdut 2506 完美网络

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2506

连通分量   缩点后形成新的图(不用新建也可以) 是一个森林

如果缩点后是就剩一个点 则答案为 0

否则 对于缩点后的某一个点   如果和它相连点(缩点后的)有大于等于2个 则无需再连

如果和它相连的有一个点 则需要加一个边连接它 如果没有点和它相连 则需要加两条

统计总共需要加的边的个数sum 因为每条边连接两个点 所以答案为 (sum+1)/2

代码:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<string>

#include<map>

#include<vector>

#include<stack>

#include<queue>

#include<set>

#include<algorithm>

#define LL long long

using namespace std;

const int N=5015;

const int M=10005;

int head[N],I;

struct node

{

    int j,next;

}side[M*2];

int dfn[N],low[N],f[N],deep;

bool visited[N],in[N];

stack<int>st;

set<int>numt[N];

void add(int i,int j)

{

    side[I].j=j;

    side[I].next=head[i];

    head[i]=I++;

}

void dfs(int x,int pre)

{

    dfn[x]=low[x]=deep++;

    st.push(x);

    in[x]=true;

    visited[x]=true;

    for(int t=head[x];t!=-1;t=side[t].next)

    {

        int j=side[t].j;

        if(j==pre)

        continue;

        if(!visited[j])

        {

            dfs(j,x);

            low[x]=min(low[x],low[j]);

        }else if(in[j])

        {

            low[x]=min(low[x],dfn[j]);

        }

    }

    if(low[x]==dfn[x])

    {

        while(st.top()!=x)

        {

            in[st.top()]=false;

            f[st.top()]=x;

            st.pop();

        }

        in[st.top()]=false;

        f[st.top()]=x;

        st.pop();

    }

}

int main()

{

    //freopen("data.in","r",stdin);

    int T;

    scanf("%d",&T);

    while(T--)

    {

       memset(head,-1,sizeof(head));

       I=0;

       int n,m;

       scanf("%d %d",&n,&m);

       while(m--)

       {

           int l,r;

           scanf("%d %d",&l,&r);

           add(l,r);

           add(r,l);

       }

       while(!st.empty())

       st.pop();

       memset(in,false,sizeof(in));

       memset(visited ,false,sizeof(visited));

       deep=1;

       int treenum=0;

       for(int i=1;i<=n;++i)

       {

           if(!visited[i])

           {

               dfs(i,-1);

               ++treenum;

           }

       }

       for(int i=1;i<=n;++i)

       numt[i].clear();

       for(int i=1;i<=n;++i)

       {

           for(int t=head[i];t!=-1;t=side[t].next)

           {

               int j=side[t].j;

               if(f[i]!=f[j])

               {

                   numt[f[i]].insert(f[j]);

               }

           }

       }

       int leftnum=0;

       int sum=0;

       for(int i=1;i<=n;++i)

       {

           if(f[i]==i)

           {

               if(numt[i].size()==0)

               {sum+=2;leftnum++;}

               if(numt[i].size()==1)

               {sum+=1;leftnum++;}

           }

       }

       if(treenum==1&&leftnum==1)

       {

           printf("0\n");

       }else

       {

           printf("%d\n",(sum+1)/2);

       }

    }

    return 0;

}

  

 

你可能感兴趣的:(网络)