EOJ 3497 group

#include<bits/stdc++.h>
using namespace std;

/*
 * 有两种可能
 * 如果只有一个连通分量则不需要坐出租车
 * 答案为0 2*N-2或者m*2 也就是边数的两倍
 * 如果有多个连通分量
 * 则每个连通分量的公交车最小次数实际是2*n-2-d n是这个连通分量的节点个数 d是这个连通分量的直径
 * 这里是生成树 也就是树的直径
 */

const int maxN=1e5+5;
vector<int> G[maxN];

int cnt_node[maxN];
bool vis[maxN];
int maxd,N;

int dfs(int x,int f,int d,int n,int & r){
    vis[x]=true;
    int cnt=0;
    if(d>maxd){
        r=x;
        maxd=d;
    }
    for(int i=0;i<G[x].size();i++){
        if(G[x][i]!=f)cnt+=dfs(G[x][i],x,d+1,n,r);
    }
    return cnt+1;
}

int main(){
    memset(vis,0,sizeof(vis));
    memset(cnt_node,0,sizeof(cnt_node));
    int m,cnt=0,a,b,res=0;
    scanf("%d%d",&N,&m);
    for(int i=0;i<m;i++){
        scanf("%d%d",&a,&b);
        G[a].push_back(b);
        G[b].push_back(a);
    }
    if(N==m+1){
        printf("0 %d",N*2-2);
        return 0;
    }
    maxd=0;
    int r1,r2;
    for(int i=1;i<=N;i++)if(!vis[i]){
        maxd=0;
        r1=r2=i;
        cnt_node[++cnt]=dfs(i,i,0,cnt,r1);
        maxd=0;
        dfs(r1,r1,0,cnt,r2);
        res+=cnt_node[cnt]*2-maxd-2;
    }
    printf("%d %d",cnt,res);
}

猜你喜欢

转载自www.cnblogs.com/TAMING/p/9400238.html