PTA 图专题总结(一)(BFS+DFS)

7.6 列出连通集(BFS + DFS)

https://pintia.cn/problem-sets/15/problems/714

输入样例:

8 6
0 7
0 1
2 0
4 1
2 4
3 5

输出样例:

{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;

int n, m;
int flag = 0;
int map[15][15] = {0};
int visited[15] = {0};
queue<int> q;

void dfs(int s) {
    visited[s] = 1;
    if(!flag)
        cout << "{";
    printf(" %d", s);
    for(int i = 0; i < n; i++)
        if(!visited[i] && map[s][i] == 1) {
            flag = 1;
            dfs(i);
        }
}

void bfs(int s) {
    visited[s] = 1;
    q.push(s);
    while(!q.empty()) {
        int l = q.front();
        q.pop();
        if(!flag)
            cout << "{";
        printf(" %d", l);
        for(int i = 0; i < n; i++)
            if(!visited[i] && map[l][i] == 1) {
                visited[i] = 1;
                q.push(i);
                flag = 1;
            }
    }
}

int main() {
    cin >> n >> m;
    while(m--) {
        int a, b;
        cin >> a >> b;
        map[a][b] = map[b][a] = 1;
    }
    
    for(int i = 0; i < n; i++)
        if(!visited[i]) {
            flag = 0;
            dfs(i);
            cout << " }" << endl;
        }
    
    memset(visited, 0, sizeof(visited));
    
    for(int i = 0; i < n; i++)
        if(!visited[i]) {
            flag = 0;
            bfs(i);
            cout << " }" << endl;
        }
    
    return 0;
}

// 第二次做的时候也尝试了一下用并查集来选择连通分量的头结点,但是WA,分析了原因是因为并查集虽然能够将把节点链接起来但是在链接过程中却会导致头结点不唯一的情况,导致答案有所变化。嗯,对并查集的理解更加深了一些。

7-7 六度空间 (BFS)

https://pintia.cn/problem-sets/15/problems/715

输入样例:

10 9
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10

输出样例:

1: 70.00%
2: 80.00%
3: 90.00%
4: 100.00%
5: 100.00%
6: 100.00%
7: 100.00%
8: 90.00%
9: 80.00%
10: 70.00%
#include <iostream>
#include <queue>
#include <cstring>

using namespace std;
#define N 1005

int n, m;
int map[N][N];
int visited[N];

int main() {
    cin >> n >> m;
    while(m--) {
        int a, b;
        cin >> a >> b;
        map[a][b] = map[b][a] = 1;
    }
    
    for(int i = 1; i <= n; i++) {
        memset(visited, 0, sizeof(visited));
        visited[i] = 1;
        queue<int> q;
        q.push(i);
        int level = 0;
        int tail;
        int last = i;
        int cnt = 1;
        while(!q.empty()) {
            int l = q.front();
            q.pop();
            for(int j = 1; j <= n; j++)
                if(!visited[j] && map[l][j] == 1) {
                    visited[j] = 1;
                    q.push(j);
                    tail = j;
                    cnt++;
                }
            if(last == l) {
                last = tail;
                level++;
            }
            if(level == 6) {
                printf("%d: %.2lf%%\n", i, cnt*1.0/n*100.0);
                break;
            }
        } 
    }
    return 0;
}

// 没啥好说的,经典的练习BFS的题目,但是不知道为啥将BFS函数中的内容写在主函数里的一个循环就直接WA,理解不能。

7-33 地下迷宫探索(DFS)

https://pintia.cn/problem-sets/15/problems/860

输入样例1:

6 8 1
1 2
2 3
3 4
4 5
5 6
6 4
3 6
1 5

输出样例1:

1 2 3 4 5 6 5 4 3 2 1

输入样例2:

6 6 6
1 2
1 3
2 3
5 4
6 5
6 4

输出样例2:

6 4 5 4 6 0
#include <iostream>
#include <cstring>

using namespace std;
#define N 1005
int flag = 0;
int visited[N] = {0};
int n, m, s;
int map[N][N];
int cnt = 0;

void dfs(int s) {
    visited[s] = true;
    cnt++;
    if(flag++)
        cout << " ";
    cout << s;
    for(int i = 1; i <= n; i++)
        if(map[s][i] && !visited[i]) {
            dfs(i);
            cout << " " << s;
        }
}

int main() {
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            map[i][j] = 0;
    cin >> n >> m >> s;
    while(m--) {
        int a, b;
        cin >> a >> b;
        map[a][b] = map[b][a] = 1;
    }
    
    dfs(s);
    if(cnt < n)
        cout << " " << 0;
    return 0;
    
}

// 不多说了经典的DFS的题目,主要是输出格式比较绕人

7-36 社交网络图中结点的“重要性”计算(BFS + 并查集)

https://pintia.cn/problem-sets/15/problems/863

输入样例:

9 14
1 2
1 3
1 4
2 3
3 4
4 5
4 6
5 6
5 7
5 8
6 7
6 8
7 8
7 9
3 3 4 9

输出样例:

Cc(3)=0.47
Cc(4)=0.62
Cc(9)=0.35
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;

#define N 10005
int map[N][N];
int visited[N] = {0};
int pre[N];
int n, m;

int find(int x) {
    if(x != pre[x])
        return pre[x] = find(pre[x]);
    return x;
}

void Union(int x, int y) {
    int a = find(x);
    int b = find(y);
    if(a != b)
        pre[a] = b;
}

int BFS(int s) {
    memset(visited, 0, sizeof(visited));
    visited[s] = 1;
    queue<int> q;
    q.push(s);
    int last = s;
    int tail;
    int level = 0;
    int cnt = 0;
    int sum = 0;
    while(!q.empty()) {
        int l = q.front();
        q.pop();
        for(int i = 1; i <= n; i++)
            if(!visited[i] && map[l][i]) {
                visited[i] = 1;
                q.push(i);
                cnt++;
                tail = i;
            }
        if(last == l) {
            last = tail;
            level++;
            sum += level*cnt;
            cnt = 0;
        }
    }
    return sum;
}

int main() {
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            map[i][j] = 0;
    for(int i = 1; i <= n; i++)
        pre[i] = i;
    
    while(m--) {
        int a, b;
        cin >> a >> b;
        map[a][b] = map[b][a] = 1;
        Union(a, b);
    }
    int cnt = 0;
    
    for(int i = 1; i <= n; i++)
        if(pre[i] == i)
            cnt++;
    
    int k;
    cin >> k;
    while(k--) {
        int a;
        cin >> a;
        if(cnt > 1) {
            printf("Cc(%d)=0.00\n", a);
        } else {
            printf("Cc(%d)=%.2f\n", a, 1.00*(n-1)/BFS(a));
        }
    }
    return 0;
}

// 并查集判断图连通性并使用BFS计算每层的个数,六度空间的变式,思路通畅之后实现就很简单了。但是第二次做的时候再一次遇到相同的问题,思路完全一致,代码大概也一样,第一遍WA,删掉全部重写直接AC,理解不能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值