PAT A1034 Head of a Gang

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
wordmeaning
thretholdn.阈(yu)值
respectivelyad.各自地
  • 思路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;
}

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值