PAT A1034 Head of a Gang
Sample Input 1:
8 59
AAA BBB 10
BBB AAA 20
AAA CCC 40
DDD EEE 5
EEE DDD 70
FFF GGG 30
GGG HHH 20
HHH FFF 10
Sample Output 1:
2
AAA 3
GGG 3
Sample Input 2:
8 70
AAA BBB 10
BBB AAA 20
AAA CCC 40
DDD EEE 5
EEE DDD 70
FFF GGG 30
GGG HHH 20
HHH FFF 10
Sample Output 2:
0
word | meaning |
---|---|
threthold | n.阈(yu)值 |
respectively | ad.各自地 |
-
思路1:
用map将name和图的顶点一一映射,在图中通过BFS遍历每个连通分量,遍历的同时累加连通分量的边权和每个结点的点权(不断更新head) -
code1(由算法笔记改写)
#include <iostream>
#include <string>
#include <map>
using namespace std;
const int maxn = 2010;
const int INF = 1000000000;
int n, k, sumPerson = 0;
int G[maxn][maxn] = {0}, v[maxn] = {0}; //顶点点权
bool flag[maxn] = {false};
map<string, int> s_int;
map<int, string> int_s;
map<string, int> Gang; //帮派head -> 人数sumMember
void DFS(int now, int& head, int& sumMember, int& totalValue){
sumMember++;
flag[now] = true;
if(v[now] > v[head]){
//更新head
head = now;
}
for(int i = 0; i < sumPerson; ++i){
if(G[now][i] > 0){
//如果now能到达i
totalValue += G[now][i];
G[now][i] = G[i][now] = 0;
if(flag[i] == false){
//如果i未被访问,DFS它
DFS(i, head, sumMember, totalValue);
}
}
}
}
void DFSTrave(){
for(int i = 0; i < sumPerson; ++i){
if(flag[i] == false){
int head = i, sumMember = 0, totalValue = 0;
DFS(i, head, sumMember, totalValue);
if(sumMember > 2 && totalValue > k){
Gang[int_s[head]] = sumMember;
}
}
}
}
int toVertex(string s){
if(s_int.find(s) != s_int.end()){
return s_int[s];
}
else{
s_int[s] = sumPerson;
int_s[sumPerson] = s;
return sumPerson++;
}
}
int main(){
cin >> n >> k;
string p1, p2;
int weight;
for(int i = 0; i < n; ++i){
cin >> p1 >> p2 >> weight;
int id1 = toVertex(p1);
int id2 = toVertex(p2);
v[id1] += weight;
v[id2] += weight;
G[id1][id2] += weight;
G[id2][id1] += weight;
}
DFSTrave();
cout << Gang.size() <<endl;
map<string, int>::iterator it;
for(it = Gang.begin(); it != Gang.end(); it++){
cout << it->first << " " << it->second <<endl;
}
return 0;
}
- code2(原版+批注)
#include <iostream>
#include <string>
#include <map>
using namespace std;
const int maxn = 2010;
const int INF = 1000000000;
int n, k, numPerson = 0; //边数, 下限k,总人数numPerson
int G[maxn][maxn] = {0}, weight[maxn] = {0}; //weight:顶点权值
bool vis[maxn] = {false};
map<int, string> n_s;
map<string, int> s_n;
map<string, int> Gang; //Gand(head) -> numMember
//DFS访问单个连通分量,nowVisit为当前访问的编号
//head为头目,numMember为成员编号,totalValue为连通块的总边数
void DFS(int nowVisit, int& head, int& numMember, int& totalValue){
numMember++;
vis[nowVisit] = true;
if(weight[nowVisit] > weight[head]){
head = nowVisit; //当前访问结点的点权大于head,更新head
}
for(int i = 0; i < numPerson; i++){
//枚举所有人
if(G[nowVisit][i] > 0){
//nowVisit能到达i
totalValue += G[nowVisit][i]; //更新总边权
G[nowVisit][i] = G[i][nowVisit] = 0; //删除这条边防止回头(遍历2次)
//!!!
if(vis[i] == false){
//如果i未被访问过
DFS(i, head, numMember, totalValue);
}
}
}
}
//DFSTrave函数遍历整个图,获取每个连通块的信息
void DFSTrave(){
for(int i = 0; i < numPerson; i++){
if(vis[i] == false){
int head = i, numMember = 0, totalValue = 0; //头目、成员数、总边权
DFS(i, head, numMember, totalValue); //遍历i所在的连通块
if(numMember > 2 && totalValue > k){
//head->人数numMember
Gang[n_s[head]] = numMember;
}
}
}
}
//change函数返回姓名str对应的编号
int change(string str){
if(s_n.find(str) != s_n.end()){ //如果在s_n中找到str
return s_n[str]; //返回编号
}
else{
s_n[str] = numPerson; //str的编号为numPerson
n_s[numPerson] = str; //numPerson对应str
return numPerson++;
}
}
int main(){
int w;
string str1, str2;
cin >> n >> k;
for(int i = 0; i < n; i++){
cin >> str1 >> str2 >> w; //输入两个端点和点权
int id1 = change(str1); //将str1转化为编号id1
int id2 = change(str2);
weight[id1] += w; //id1的点权增加w
weight[id2] += w;
G[id1][id2] += w; //边id1->id2的边权+w
G[id2][id1] += w;
}
DFSTrave(); //遍历整个连通块,获取Gang的信息
cout << Gang.size() <<endl; //输出Gand的个数
map<string, int>::iterator it;
for(it = Gang.begin(); it != Gang.end(); it++){
//遍历所有Gang
cout << it->first << " " << it->second <<endl;
}
return 0;
}
- T2 code:
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
const int maxn = 2010; //Wrong 1: 样例3,不同的人数可能有2000以上!
int n, k;
int G[maxn][maxn], weight[maxn];
bool flg[maxn];
unordered_map<int, string> Find;
unordered_map<string, int> Id;
map<string, int> Gang;
int P_id = 0;
int Change(string name){
if(Id.find(name) != Id.end()){
return Id[name];
}else{
Id[name] = P_id;
Find[P_id] = name;
return P_id++;
}
}
vector<string> head;
void DFS(int id, int & sum_p, int & sum_w, int & h){
sum_p++;
flg[id] = true;
if(weight[id] > weight[h]){
h = id;
}
for(int i = 0; i < P_id; ++i){
if(G[id][i] != 0){
sum_w += G[id][i];
G[i][id] = 0;
if(flg[i] == false) DFS(i, sum_p, sum_w, h);
}
}
}
void DFSTrave(){
for(int i = 0; i < P_id; ++i){
if(flg[i] == false){
int sum_p = 0, sum_w = 0, h = i;
DFS(i, sum_p, sum_w, h);
if(sum_p > 2 && sum_w > k){
Gang[Find[h]] = sum_p;
}
}
}
}
int main(){
scanf("%d %d", &n, &k);
// fill(G[0], G[0] + maxn * maxn, 0);
for(int i = 0; i < n; ++i){
string t_name1, t_name2;
cin >> t_name1 >> t_name2;
int id1 = Change(t_name1), id2 = Change(t_name2), call_len;
scanf("%d", &call_len);
weight[id1] += call_len;
weight[id2] += call_len;
G[id1][id2] += call_len;
G[id2][id1] = G[id1][id2];
}
DFSTrave();
printf("%d\n", Gang.size());
for(auto it = Gang.begin(); it != Gang.end(); ++it){
cout << it->first << " " << it->second <<endl;
}
return 0;
}
- 思路 2 : BFS版
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2020;
int G[maxn][maxn], weight[maxn];
bool vis[maxn];
unordered_map<string, int> get_id;
unordered_map<int, string> get_name;
int idex = 0;
int Change(string v)
{
if(get_id.find(v) == get_id.end())
{
get_id[v] = idex;
get_name[idex] = v;
return idex++;
}else return get_id[v];
}
void BFS(int start, int & sum, int & cnt, int & head)
{
queue<int> q;
q.push(start);
vis[start] = true;
int Max = 0;
while(!q.empty())
{
int now = q.front();
q.pop();
if(weight[now] > Max)
{
Max = weight[now];
head = now;
}
cnt++;
for(int i = 0; i < idex; ++i)
{
if(G[now][i] != 0)
{
sum += G[now][i];
G[i][now] = 0;
if(vis[i] == false)
{
vis[i] = true;
q.push(i);
}
}
}
}
}
void BFSTraversal(int k)
{
map<string, int> gang;
for(int i = 0; i < idex; ++i)
{
int cnt = 0, sum = 0, head;
if(vis[i] == false)
{
BFS(i, sum, cnt, head);
if(cnt > 2 && sum > k) gang[get_name[head]] = cnt;
}
}
printf("%d\n", gang.size());
for(auto it = gang.begin(); it != gang.end(); ++it)
{
printf("%s %d\n", it->first.c_str(), it->second);
}
}
int main()
{
int n, k;
scanf("%d %d", &n, &k);
for(int i = 0; i < n; ++i)
{
string p1, p2;
int call_len;
cin >> p1 >> p2 >> call_len;
int id1 = Change(p1), id2 = Change(p2);
G[id1][id2] += call_len;
G[id2][id1] += call_len;
weight[id1] += call_len;
weight[id2] += call_len;
}
BFSTraversal(k);
return 0;
}
-
留坑:并查集写法:
-
填坑:感觉写的有点乱
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2020;
int weight[maxn];
int idex = 0;
unordered_map<string, int> get_id;
unordered_map<int, string> get_name;
int Change(string s)
{
if(get_id.find(s) == get_id.end())
{
get_id[s] = idex;
get_name[idex] = s;
return idex++;
}else return get_id[s];
}
struct Father
{
int r, weight;
Father(){ r = -1; weight = 0; }
}father[maxn];
int FindRoot(int x)
{
int tmp = x;
while(father[x].r > 0)
{
x = father[x].r;
}
while(father[tmp].r > 0)
{
int tmp2 = tmp;
tmp = father[tmp].r;
father[tmp2].r = x;
}
return x;
}
void Union(int a, int b, int cost)
{
int ra = FindRoot(a), rb = FindRoot(b);
if(ra != rb)
{
father[rb].weight += father[ra].weight;
father[rb].r += father[ra].r;
father[ra].r = rb;
}
father[rb].weight += cost;
}
int Max[maxn], head[maxn];
bool first[maxn];
void Count(int k)
{
map<string, int> gang;
for(int i = 0; i < idex; ++i)
{
int r = FindRoot(i);
if(weight[i] > Max[r])
{
Max[r] = weight[i];
head[r] = i;
}
}
for(int i = 0; i < idex; ++i)
{
int r = FindRoot(i);
if(first[r] == false && father[r].weight > k && abs(father[r].r) > 2)
{
gang[get_name[head[r]]] = abs(father[r].r);
first[r] = true;
}
}
printf("%d\n", gang.size());
for(auto it = gang.begin(); it != gang.end(); ++it)
{
printf("%s %d\n", it->first.c_str(), it->second);
}
}
int main()
{
int n, k;
scanf("%d %d", &n, &k);
for(int i = 0; i < n; ++i)
{
string p1, p2;
int cost;
cin >> p1 >> p2 >> cost;
int id1 = Change(p1), id2 = Change(p2);
weight[id1] += cost;
weight[id2] += cost;
Union(id1, id2, cost);
}
Count(k);
return 0;
}