PTA甲級—圖

1.圖的遍歷html

1013 Battle Over Cities (25 分)node

一種方法使用dfs求連通塊的個數ios

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
using namespace std;
const int maxn = 1e4+100;
int n, m, k, u, v, q;
int d[maxn];
bool vis[maxn];
vector<int> g[maxn];
void dfs(int u){
    vis[u] = 1;
    for(int i = 0; i < g[u].size(); i++){
        int v = g[u][i];
        if(v!=q&&!vis[v]) dfs(v);
    }
}
int main(){
    scanf("%d%d%d", &n, &m, &k);
    while(m--){
        scanf("%d%d", &u, &v);
        g[u].pb(v), g[v].pb(u);
    }
    while(k--){
        scanf("%d", &q);
        for(int i = 1; i <= n; i++) vis[i] = 0;
        int cnt = 0;
        for(int i = 1; i <= n; i++){
            if(i!=q&&!vis[i]) dfs(i), cnt++;
        }
        printf("%d\n", cnt-1);
    }
} 
View Code

另一種方法是用並查集,胡凡的作法對每次查詢從新構建集合,這樣感受太慢了,不必,本質都是求連通塊的個數ide

 

1021 Deepest Root (25 分)測試

首先判斷給定的圖是不是顆樹,須要知道的是連通、邊數爲n-1的圖必定是棵樹。輸入的邊數是n-1,咱們只須要判斷連通份量是否爲1便可,能夠經過並查集或者是dfs計數來判斷。接下來只須要記錄樹的直徑的端點,並按照順序輸出。注意不能加入重複的點,有個特殊樣例n = 1能夠用來測試spa

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
using namespace std;
const int maxn = 1e4+100;
int n, u, v, tot, t, ans, f[maxn], cnt[maxn], s[maxn], node[maxn];
vector<int> g[maxn];
bool vis[maxn];
int find(int x){
    if(f[x]!=x) f[x] = find(f[x]);
    return f[x];
}
void merge(int x, int y){
    x = find(x), y = find(y);
    f[x] = y;
}
void dfs(int u, int fa, int step){
    if(ans<step) ans = step, s[1] = u, t = 1;
    else if(ans==step) s[++t] = u;
    for(int i = 0; i < g[u].size(); i++){
        int v = g[u][i];
        if(v!=fa) dfs(v, u, step+1);
    }
}
int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) f[i] = i; 
    for(int i = 1; i <= n-1; i++){
        scanf("%d%d", &u, &v);
        g[u].pb(v), g[v].pb(u);
        if(find(u)!=find(v)) merge(u, v);
    }
    for(int i = 1; i <= n; i++) cnt[find(i)]++;
    for(int i = 1; i <= n; i++)
        if(cnt[i]!=0) tot++;
    if(tot!=1) printf("Error: %d components", tot);
    else{
        dfs(1, 0, 0);
        int k = 0;
        for(int i = 1; i <= t; i++) 
            node[++k] = s[i], vis[s[i]] = 1;
        dfs(s[1], 0, 0);
        for(int i = 1; i <= t; i++) 
            if(!vis[s[i]]) node[++k] = s[i], vis[s[i]] = 1;
        sort(node+1, node+1+k);
        for(int i = 1; i <= k; i++) printf("%d\n", node[i]);
    }
}
View Code

Reference:.net

樹的直徑及其證實:
https://www.cnblogs.com/Khada-Jhin/p/10195287.html
https://bbs.csdn.net/topics/3401182433d

 

1034 Head of a Gang (30 分)code

題目要求知足條件的聯通份量的信息,用並查集模擬便可,寫的時候須要注意代碼細節。特別提示:節點的total weight能夠用和它相連的邊權之和來表示。component

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
using namespace std;
const int maxn = 1e5+100;
int n, wei, val;
int t, p[maxn], k, ans[maxn], dig[3];
int f[maxn], d[maxn], cnt[maxn], tot[maxn], u[maxn], v[maxn];
string s1, s2, str[maxn];
bool vis[maxn];
int find(int x){
    if(f[x]!=x) f[x] = find(f[x]);
    return f[x];
}
void merge(int x, int y){
    x = find(x), y = find(y);
    d[x] < d[y] ? f[x] = y : f[y] = x;
}
int get_hash(string s){
    int id = (s[0]-'A')*26*26+(s[1]-'A')*26+s[2]-'A';
    str[id] = s;
    return id;
}
int main(){
    scanf("%d%d", &n, &wei);
    for(int i = 1; i <= n; i++){
        cin >> s1 >> s2 >> val;
        u[i] = get_hash(s1), v[i] = get_hash(s2);
        if(!vis[u[i]]) p[++t] = u[i], f[u[i]] = u[i], vis[u[i]] = 1;
        if(!vis[v[i]]) p[++t] = v[i], f[v[i]] = v[i], vis[v[i]] = 1;
        d[u[i]] += val, d[v[i]] += val;
    }
    for(int i = 1; i <= n; i++){
        if(find(u[i])!=find(v[i])) merge(u[i], v[i]);
    }
    for(int i = 1; i <= t; i++) {
        int head = find(p[i]);
        cnt[head]++, tot[head] += d[p[i]];
    }
    for(int i = 1; i <= t; i++){
        int head = find(p[i]);
        if(cnt[head]<=2||tot[head]<=wei*2) continue;
        if(vis[head]) ans[++k] = head, vis[head] = 0;
    }
    sort(ans+1, ans+1+k);
    printf("%d\n", k);
    for(int i = 1; i <= k; i++) printf("%s %d\n", str[ans[i]].c_str(), cnt[ans[i]]);
}
View Code
相關文章
相關標籤/搜索