Hướng dẫn giải của Tìm khớp và cầu (Cơ bản)
Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Lưu ý: Các code mẫu dưới đây chỉ mang tính tham khảo và có thể không AC được bài tập này
Code mẫu của flashmt
uses math; var n,m,i,j,cnt,cau,khop:longint; p,low,num,cha,con:array[1..10010] of longint; a,b,c:array[1..100010] of longint; d:array[1..10010] of boolean; procedure visit(x,y:longint); var i:longint; begin inc(cnt); num[x]:=cnt; low[x]:=cnt; cha[x]:=y; for i:=p[x]+1 to p[x+1] do if a[i]<>y then begin if num[a[i]]>0 then low[x]:=min(low[x],num[a[i]]) else begin visit(a[i],x); low[x]:=min(low[x],low[a[i]]); end; end; end; begin read(n,m); for i:=1 to m do begin read(b[i],c[i]); inc(p[b[i]]); inc(p[c[i]]); end; for i:=2 to n+1 do inc(p[i],p[i-1]); for i:=1 to m do begin a[p[b[i]]]:=c[i]; dec(p[b[i]]); a[p[c[i]]]:=b[i]; dec(p[c[i]]); end; for i:=1 to n do if cha[i]=0 then visit(i,-1); for i:=1 to n do if cha[i]>0 then inc(con[cha[i]]); for i:=1 to n do begin j:=cha[i]; if j<0 then continue; if low[i]>=num[i] then inc(cau); if d[j] then continue; if (low[i]>=num[j]) and ((cha[j]<>-1) or (con[j]>1)) then begin d[j]:=true; inc(khop); end; end; writeln(khop,' ',cau); end.
Code mẫu của happyboy99x
#include<cstdio> #include<vector> using namespace std; const int N = 10005; int n, m, cut, bridge, t, d[N], low[N]; vector<vector<int> > g; void enter() { scanf("%d%d",&n,&m); g.resize(n); for(int i = 0; i < m; ++i) { int u, v; scanf("%d%d",&u,&v); g[--u].push_back(--v); g[v].push_back(u); } } void dfs(int u, int p) { low[u] = d[u] = ++t; int iscut = 0, nchild = 0; for(vector<int>::iterator v = g[u].begin(); v != g[u].end(); ++v) if(d[*v] == 0) { ++nchild; dfs(*v, u); low[u] = min(low[u], low[*v]); if(low[*v] >= d[u] && p != -1 || nchild == 2 && p == -1) iscut = 1; if(low[*v] >= d[*v]) ++bridge; } else if(*v != p) low[u] = min(low[u], d[*v]); cut += iscut; } void solve() { for(int u = 0; u < n; ++u) if(d[u] == 0) dfs(u, -1); printf("%d %d\n", cut, bridge); } int main() { enter(); solve(); return 0; }
Code mẫu của ladpro98
#include <bits/stdc++.h> const int N = 10005; const int oo = 123456789; using namespace std; vector<int> a[N]; int par[N], low[N], num[N], nchild[N]; bool cut[N]; int m, n, Time, bridge, art; void DFS(int u) { num[u] = ++Time; low[u] = n+1; int i, v; for(i=0; i<a[u].size(); i++) { v = a[u][i]; if (v == par[u]) continue; if (par[v] == 0) { nchild[u]++; par[v] = u; DFS(v); low[u] = min(low[u], low[v]); } else low[u] = min(low[u], num[v]); } } int main() { scanf("%d %d", &n, &m); int i, u, v; for(i=1; i<=m; i++) { scanf("%d %d", &u, &v); a[u].push_back(v); a[v].push_back(u); } for(i=1; i<=n; i++) if (par[i] == 0) { par[i] = -1; DFS(i); } //bridges for(v=1; v<=n; v++) { u = par[v]; if (u != -1 && low[v] >= num[v]) bridge++; } for(v=1; v<=n; v++) if (par[v] != -1) { u = par[v]; if (low[v] >= num[u]) cut[u] = cut[u] || (par[u] != -1) || (nchild[u] >= 2); } for(i=1; i<=n; i++) if (cut[i]) art++; printf("%d %d", art, bridge); return 0; }
Code mẫu của RR
#include <cstdio> #include <iostream> #include <algorithm> #include <string> #include <cstring> #include <cmath> #include <vector> #include <cstdlib> #include <set> #include <queue> #include <stack> #include <memory.h> #include <cassert> #include <sstream> #define oo 1000111000 #define PI acos(-1.0) #define FOR(i,a,b) for(int i = (a), _b = (b); i <= _b; i++) #define FORD(i,a,b) for(int i = (a), _b = (b); i >= _b; i--) #define REP(i,n) for(int i = 0, _n = (n); i < _n; i++) #define REPD(i,n) for(int i = (n) - 1; i >= 0; i--) #define PB push_back #define MP make_pair #define F first #define S second #define SIZE(c) (c).size() #define RESET(c,x) memset(c,x,sizeof(c)) using namespace std; typedef pair <int, int> PII; typedef long long LL; inline void OPEN(const string &s) { freopen((s + ".in").c_str(), "r", stdin); freopen((s + ".out").c_str(), "w", stdout); } #define MAXV 100000 int V; vector <int> G[MAXV + 5]; int dfs_low[MAXV + 5], dfs_num[MAXV + 5], dfs_parent[MAXV + 5]; int dfsNumberCounter, dfsRoot, rootChildren; bool articulation_vertex[MAXV + 5]; int nBridge, nAp; void articulationPointAndBridge(int u) { dfs_low[u] = dfs_num[u] = dfsNumberCounter++; REP (j, SIZE(G[u])) { int v = G[u][j]; if (dfs_num[v] == -1) { dfs_parent[v] = u; if (u == dfsRoot) rootChildren++; articulationPointAndBridge(v); if (dfs_low[v] >= dfs_num[u]) articulation_vertex[u] = true; if (dfs_low[v] > dfs_num[u]) ++nBridge; dfs_low[u] = min(dfs_low[u], dfs_low[v]); } else if (v != dfs_parent[u]) dfs_low[u] = min(dfs_low[u], dfs_num[v]); } } int main() { scanf("%d", &V); int m; scanf("%d", &m); while (m--) { int u, v; scanf("%d%d", &u, &v); --u; --v; G[u].PB(v); G[v].PB(u); } dfsNumberCounter = 0; RESET(dfs_num, -1); RESET(dfs_low, 0); RESET(dfs_parent, 0); RESET(articulation_vertex, 0); REP (i, V) if (dfs_num[i] == -1) { dfsRoot = i; rootChildren = 0; articulationPointAndBridge(i); articulation_vertex[dfsRoot] = (rootChildren > 1); } REP (i, V) if (articulation_vertex[i]) ++nAp; printf("%d %d\n", nAp, nBridge); return 0; }
Code mẫu của skyvn97
#include<set> #include<cstdio> #include<vector> #include<cstring> #define MAX 10101 using namespace std; typedef pair<int,int> ii; vector<int> g[MAX]; set<ii> bl; int m,n; int low[MAX]; int num[MAX]; int nch[MAX]; bool cutv[MAX]; int cnt; int nb,nc; void loadgraph(void) { scanf("%d",&n); scanf("%d",&m); int i,u,v; for (i=1;i<=n;i=i+1) g[i].clear(); for (i=1;i<=m;i=i+1) { scanf("%d",&u); scanf("%d",&v); g[u].push_back(v); g[v].push_back(u); } } int min(const int &x,const int &y) { if (x<y) return (x); else return (y); } void visit_bridge(const int &u) { int i,v; cnt++; num[u]=cnt; low[u]=n+1; for (i=0;i<g[u].size();i=i+1) { v=g[u][i]; if (bl.find(ii(u,v))!=bl.end()) continue; bl.insert(ii(v,u)); if (num[v]==0) { visit_bridge(v); if (low[v]>num[u]) nb++; low[u]=min(low[u],low[v]); } else low[u]=min(low[u],num[v]); } } void count_bridge(void) { memset(low,0,sizeof low); memset(num,0,sizeof num); bl.clear(); nb=0; cnt=0; int i; for (i=1;i<=n;i=i+1) if (num[i]==0) visit_bridge(i); printf("%d",nb); } void visit_cutvert(const int &u) { int i,v; cnt++; num[u]=cnt; low[u]=n+1; cutv[u]=false; for (i=0;i<g[u].size();i=i+1) { v=g[u][i]; if (num[v]==0) { nch[u]++; visit_cutvert(v); cutv[u]=cutv[u]||(low[v]>=num[u]); low[u]=min(low[u],low[v]); } else low[u]=min(low[u],num[v]); } } void count_cutvert(void) { memset(low,0,sizeof low); memset(num,0,sizeof num); memset(nch,0,sizeof nch); nc=0; cnt=0; int i; for (i=1;i<=n;i=i+1) { if (num[i]==0) { visit_cutvert(i); if (nch[i]<2) cutv[i]=false; } } for (i=1;i<=n;i=i+1) nc+=cutv[i]; printf("%d ",nc); } int main(void) { loadgraph(); count_cutvert(); count_bridge(); return 0; }
Code mẫu của khuc_tuan
#include <iostream> #include <vector> #include <cstdio> #include <set> using namespace std; int n, m; vector<pair<int,int> > ke[10010]; int num[10010], low[10010], fa[10010]; bool mark[10010], vsting[10010], khop[10010]; int tt = 0, sokhop, socau; void dfs(int i, int edge) { vsting[i] = true; mark[i] = true; num[i] = tt++; low[i] = num[i]; int sc = 0; for(int k=0;k<ke[i].size();++k) { int j = ke[i][k].first; if(!mark[j]) { ++sc; fa[j] = i; dfs(j, ke[i][k].second); low[i] = min( low[i], low[j]); } else if(ke[i][k].second != edge && vsting[j]) low[i] = min( low[i], num[j]); } if(edge != -1 && low[i] == num[i]) ++socau; if(edge == -1) { if(sc > 1) khop[i] = true; else khop[i] = false; } if(edge != -1 && low[i] >= num[fa[i]]) khop[fa[i]] = true; vsting[i] = false; } int main() { scanf("%d%d", &n, &m); set<pair<int,int> > se; for(int i=0;i<m;++i) { int u, v; scanf("%d%d", &u, &v); if(!se.count(make_pair(u,v))) { ke[u].push_back(make_pair(v,i)); ke[v].push_back(make_pair(u,i)); se.insert(make_pair(u,v)); se.insert(make_pair(v,u)); } } for(int i=1;i<=n;++i) if(!mark[i]) { dfs(i, -1); } for(int i=1;i<=n;++i) if(khop[i]) ++sokhop; cout << sokhop << " " << socau << endl; return 0; }
Bình luận