Kattis

题目传送门:Kattis - hoppers  Hoppers

题目大意:

你是一个黑客,现在你发明了一种感染病毒,这种感染病毒能够感染到与该主机相隔一个点的主机。

存在一个无向图,每个点代表一台主机,每条无向边表示两台主机相连,现在你有个计划是通过感

染一个电脑让所有电脑感染,你可以为两条电脑之间加边,需要你求出最少加多少条边能够完成计划

分析:

我们能够发现奇数环中任何一个点被感染都能够使奇数环中所有的点感染。因此我们可以利用该性质。

为了满足条件(感染一个点使所有点被感染)存在几种情况:

1.如果存在不连通的一个奇数环和一个偶数环:需要加一条边,将奇数环和偶数环相连即可

2.如果存在两个不联通的奇数环:需要加一条边

3.如果存在两个不连通的偶数环:需要加两条边:一条边将两个偶数环联通,一条边加进任意一个偶数环中

构成一个奇数环。

因此我们可以得出这题的解法:通过dfs判断存在多少个联通块,如果存在n个联通块则需要n-1条边将所有联通

块连接。再每次进行dfs时判断,每个联通块中是否存在奇数环,如果存在奇数环则无需另外加一条边,否则加一条边

代码:

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cmath>
using namespace std;
const int MAX=500009;
int n,m,u,v;
vector<int>G[MAX];
int vis[MAX];
int odd=1;
bool dfs(int u,int val)
{
    vis[u]=val;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(!vis[v])dfs(v,val+1);
        else if((abs(vis[u]-vis[v])+1)%2!=0)odd=0;        //存在奇数环
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++){
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            dfs(i,1);
            ans++;        //记录存在多少个联通块 
        }    
    }
    printf("%d
",ans-1+odd);
    return 0;
} 

 

原文地址:https://www.cnblogs.com/LjwCarrot/p/10739594.html