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); } }
另一種方法是用並查集,胡凡的作法對每次查詢從新構建集合,這樣感受太慢了,不必,本質都是求連通塊的個數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]); } }
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]]); }