写目录
-
- 邻接表的构建
- 邻接表DFS
- AcWing 846. 树的重心
-
- pat 1034 Head of a Gang
-
- 无向图/有向图的深度搜索,各连通块分别搜索
- 有向图版
- 无向图版
邻接表的构建
邻接表DFS
const int N = 1e5 + 10, M = 2*N;
int h[N], e[M], ne[M];
bool visited[M];
int n = 0, idx = 0;
void add(int a, int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
void dfs(int u)
{
cout << u << " ";
visited[u] = true;
for(int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if(!visited[j])
dfs(j);
}
}
int main()
{
memset(h,-1,sizeof h);
cin >> n;
int a, b;
for(int i = 0; i < n - 1; ++i)
{
cin >> a >> b;
add(a, b);
add(b, a);
}
dfs(1);
return 0;
}
AcWing 846. 树的重心
无向图
- 主要找删除某个顶点后各连通块中点个数量的关系
- 连通点数是个数
const int N = 1e5 + 10, M = 2*N;
int h[N], e[M], ne[M];
bool visited[M];
int n = 0, idx = 0;
void add(int a, int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
int ans = N;
int dfs(int u)
{
visited[u] = true;
int sum = 1;
int ret = 0;
for(int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if(!visited[j])
{
int tmp = dfs(j);
ret = max(ret, tmp);
sum += tmp;
}
}
ret = max(ret, n - sum);
ans = min(ans, ret);
return sum;
}
int main()
{
memset(h,-1,sizeof h);
cin >> n;
int a, b;
for(int i = 0; i < n - 1; ++i)
{
cin >> a >> b;
add(a, b);
add(b, a);
}
dfs(1);
cout << ans;
return 0;
}
pat 1034 Head of a Gang
无向图/有向图的深度搜索,各连通块分别搜索
- 各连通块即各帮派
- 这题有向图无向图都能做
- 差别是无向图会将通话时间加倍,所以判断时要将总时长 / 2
有向图版
const int N = 2*(1e3 + 10);
unordered_map<string, int> index;
unordered_map<int, string> index_name;
vector<int> each_time(N);
vector<Node> calls[N];
vector<Node> ret;
bool visited[N];
int n, m, idx = 0;
vector<string> start;
struct Node
{
Node(){}
Node(string n, int t):name(n), time(t){}
string name;
int time;
};
void dfs(int u, int &nsum, int &tsum, int &head)
{
visited[u] = true;
if(each_time[u] > each_time[head])
head = u;
for(int i = 0; i < calls[u].size(); ++i)
{
int j = index[calls[u][i].name];
tsum += calls[u][i].time;
if(!visited[j])
{
nsum += 1;
dfs(j, nsum, tsum, head);
}
}
}
bool check_in(string s, int &ci)
{
if(index.count(s))
ci = index[s];
else
{
ci = idx;
index_name[ci] = s;
index[s] = idx++;
}
}
void add(string s1, string s2, int t)
{
Node m_node;
m_node.time = t;
m_node.name = s2;
int i1 = 0, i2 = 0;
check_in(s1, i1);
check_in(s2, i2);
calls[i1].push_back(m_node);
each_time[i1] += t;
each_time[i2] += t;
}
bool cmp(Node n1, Node n2)
{
return n1.name < n2.name;
}
int main()
{
cin >> n >> m;
string s1, s2;
int t;
for(int i = 0; i < n; i++)
{
cin >> s1 >> s2 >> t;
if(!index.count(s1) && !index.count(s2))
start.push_back(s1);
add(s1, s2, t);
}
for(auto &s : start)
{
int head = index[s];
int tsum = 0, nsum = 1;
dfs(head, nsum, tsum, head);
if(tsum > m && nsum > 2)
ret.push_back({index_name[head], nsum});
}
sort(ret.begin(), ret.end(), cmp);
cout << ret.size();
for(auto &p : ret)
cout << endl << p.name << " " << p.time;
return 0;
}
无向图版
void add(string s1, string s2, int t)
{
...
each_time[i1] += t;
}
int main()
{
...
add(s1, s2, t);
add(s2, s1, t);
...
if(tsum / 2 > m && nsum > 2)
ret.push_back({index_name[head], nsum});
...
}