其他分享
首页 > 其他分享> > 1414-二步侠PIPI

1414-二步侠PIPI

作者:互联网

题目描述
已知有n个城市,城市之间有m条道路。PIPI准备从1号城市出发,游览剩下所有的城市。但是PIPI有个强迫症,他的行动是二步流的。什么是二步流呢?比如:1号城市和2号城市之间有条道路,2号城市和3号城市之间有条道路,PIPI的路线为1->2->3或者1->2->1。但他只是经过了2号城市到达了3号或1号城市进行游览,而2号城市永远只能经过而无法游览到。
为了满足自己的强迫症,同时又游览所有城市,财大气粗的PIPI可以在任意城市之间修建道路。
出于节约成本低碳环保考虑,PIPI最少修建多少条道路即可游览所有城市?
输入
第一行两个整数n,m,其中:3<=n<=105,0<=m<=105。
接下来m行,每行两个正整数u,v(u,v<=n),表示u号城市与v号城市之间有一条道路。
PS:数据保证无自环,不保证不会出现重边。
输出
输出PIPI最少需要修建的道路条数。
样例输入
5 4
1 2
2 3
3 4
4 5
样例输出
1

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+7;
vector<int> mp[N];
int color[N];
int flag=1;   ///flag为1时表示有二分图
void DFS(int x){
    //if(flag==0) return;  ///这个地方不能剪枝,判断连通图要搜到底,反例很容易想
    for(int i=0;i<mp[x].size();i++){
        int next = mp[x][i];
        if(!color[next]) color[next]=color[x]^3,DFS(next);
        else if(color[next]==color[x]) flag=0;    ///表示此图不是二分图
    }
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    while(m--){
        int u,v;
        scanf("%d%d",&u,&v);
        mp[u].push_back(v);
        mp[v].push_back(u);
    }
    ///遍历所有顶点统计连通分量个数,sum表示联通分量个数,并且对所有连同分量做出判断其是否为二分图
    int sum=0;
    for(int i=1;i<=n;i++) if(!color[i]) color[i]=1,DFS(i),sum++;
    ///首先令ans=sum-1;然后判断,如果所有子图均为二分图,则答案为ans+1,否则答案为ans
    if(flag==0) printf("%d\n",sum-1);  ///如果存在图不为二分图ans就为答案
    else printf("%d\n",sum);       ///如果所有的图均为二分图则ans+1为最终答案
    return 0;
}

整体思路,如果子图不全为二分图,则需要加的路径数等于连通分量数-1,否则要加的路径数就为连通分量数,注意这里的DFS函数的作用,不仅要用来判断二分图,而且还要用来判断连通子图的数量

标签:二分,二步,int,PIPI,城市,next,color,1414
来源: https://blog.csdn.net/weixin_43211195/article/details/113735766