首页 > 其他分享 >1013 Battle Over Cities

1013 Battle Over Cities

时间:2023-01-29 19:22:17浏览次数:40  
标签:连通 ch int Over MAXN Battle c2 c1 Cities

1013 Battle Over Cities

题目描述

题意理解

题意很简单,给出一张图,问如果去掉其中一个节点以及与这条节点相连的边,需要再添加几条边才能使图重新连通。

解题的关键在于找到要补的边数与图的关系,细想一下马上就知道,对于n个连通分量,使之变成一张连通图需要n-1条边。所以这道题的实质就是求去掉某个节点之后,图中有几个连通分量。

求连通分量的个数有很多方法,dfs、并查集等等,我一开始想到的是并查集,思路是跳过被除掉的节点来建立并查集,最后根的数量减一就是答案,但是却超时了,也想不出优化的办法。

后来就想到dfs,从第一座城市开始深搜,凡是搜到过的城市(也就是联通的城市)都标记为true,再从仍未搜索过的城市开始下一轮深搜,直到所有城市都标记为true,至于被占领的城市一开始就标记为true,这样就可以绕开它了。最后,深搜的次数就是连通分量的个数,再减一就是答案。

代码

首先是能AC的dfs:

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

int n, m, k;
int cmap[MAXN][MAXN], visited[MAXN];

void reset(int t)
{
    for (int i = 1; i <= n; i++)
        visited[i] = false;
    visited[t] = true;
}

void dfs(int c, int t)
{
    visited[c] = true;
    for (int i = 1; i <= n; i++)
        if (!visited[i] && cmap[c][i] && i != t)
            dfs(i, t);
}

int solve(int t)
{
    reset(t);
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        if (!visited[i]) {
            dfs(i, t);
            cnt++;
        }
    }
    return cnt - 1;
}

int main()
{
    scanf("%d %d %d", &n, &m, &k);
    for (int i = 0; i < m; i++) {
        int c1, c2; scanf("%d %d", &c1, &c2);
        cmap[c1][c2] = cmap[c2][c1] = 1;
    }
    while (k--) {
        int t; scanf("%d", &t);
        printf("%d", solve(t));
        if (k) printf("\n");
    }
    return 0;
}

最后贴一个并查集(测试样例四超时):

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

int n, m, k;
int cmap[MAXN][MAXN], sset[MAXN];

int find(int ch, int* s)
{
    if (s[ch] == ch) return ch;
    else return find(s[ch], s);
}

void join(int c1, int c2, int* s) 
{
    int fa1 = find(c1, s);
    int fa2 = find(c2, s);
    s[fa1] = fa2;
}

int solve(int t)
{
    for (int i = 1; i <= n; i++) sset[i] = i;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            if (i == t || i == j) break;
            if (j == i) continue;
            if (cmap[i][j]) {
                join(j, i, sset);
            }
        }
    }
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        if (sset[i] == i && i != t)
            cnt++;
    }
    return cnt - 1;
}

int main()
{
    cin >> n >> m >> k;
    for (int i = 0; i < m; i++) {
        int c1, c2; cin >> c1 >> c2;
        cmap[c1][c2] = cmap[c2][c1] = 1;
        if (c1 > c2) swap(c1, c2);
        join(c1, c2, sset);
    }
    while (k--) {
        int t; cin >> t;
        cout << solve(t);
        if (k) cout << endl;
    }
    return 0;
}

标签:连通,ch,int,Over,MAXN,Battle,c2,c1,Cities
From: https://www.cnblogs.com/codas/p/17073650.html

相关文章