PAT A1034 邻接表实现

PAT A1034 邻接表实现 

实现思路参考 《算法笔记》P354

#include<iostream>
#include<vector>
#include<map>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN = 10000;

//图节点
struct node{
	int to,weight,rec;
	node(){}
	node(int to, int weight,int rec):to(to),weight(weight),rec(rec){}
};

//答案节点  存放答案
struct  ansNode{
	string name;
	int num;
	int sum;
	bool operator <(ansNode & b){
		return name<b.name;
	}
};

// string  和 int 之间的映射
map<string,int> str2int;
map<int,string> int2str; 
 
//节点是否访问
int vis[MAXN];
//每个节点的权值总和
int weight[MAXN];
//邻接表
vector<node> map_[MAXN];
//所有点的数量
int PerNum;
//边过滤map
map<pair<int,int>, int > edge;
int N,K;

void init(){
	memset(vis,0,sizeof(vis));
	memset(weight,0,sizeof(weight));
	PerNum = 0; 
}

//
void add_edge(int a,int b,int num){
	map_[a].push_back(node(b,num,map_[b].size()));
	map_[b].push_back(node(a,num,map_[a].size()-1));	
}


int change(string a){
	if(str2int.find(a) == str2int.end()){
		PerNum ++;
		str2int[a] = PerNum;
		int2str[PerNum] = a;
		return PerNum;
	}
	return str2int[a];
}

void dfs(int v,int &head,int &num,int &sum){
	
	if(vis[v] == true)return;
    //找最大的权的点
	if(weight[v]> weight[head]) head = v;	
	vis[v] = true;
	num++;
	for(int i=0;i<map_[v].size();i++){
		node temp = map_[v][i];
		sum+= temp.weight;
		map_[temp.to][temp.rec].weight = 0;
		dfs(temp.to,head,num,sum);
	}
}
vector<ansNode> anslist;

void travels(){
	
	// 保证对整个图进行遍历 
	for(int i=1;i<=PerNum;i++){
		if(vis[i] == true) continue;
		int num = 0;
		int sum = 0;
		int head = i;
		// 对连通的点进行遍历 
		dfs(i,head,num,sum);
		if(sum >= K && num >2){
			ansNode ansnode;
			ansnode.name = int2str[head];
			ansnode.num = num;
			ansnode.sum = sum;
			anslist.push_back(ansnode);
		}
	}
}

int main(){
	init();

	PerNum = 0;
	scanf("%d%d",&N,&K);
	for(int i=0;i<N;i++){
		string a,b;
		int num;
		cin>>a>>b>>num; 
		int indexa = change(a);
		int indexb = change(b);
		weight[indexa] +=num;
		weight[indexb] +=num;
		//先用map 过滤一下,把重边都重新加起来 
		if(indexa > indexb)
			swap(indexa,indexb);
		if(edge.find(make_pair(indexa,indexb)) == edge.end()){
			edge[make_pair(indexa,indexb)] = num;
		}else{
			edge[make_pair(indexa,indexb)] += num;			
		}
	}
	
	//过滤后再添加边 
	map<pair<int,int>, int >::iterator it = edge.begin();
	for(;it!=edge.end();it++){
		pair<int,int> temp = it->first;
		int a = temp.first;
		int b = temp.second;
		add_edge( a, b, it->second);
	}
	//开始遍历每个点 
	travels();
	
	sort(anslist.begin(),anslist.end());
	
	printf("%d\n",anslist.size());
	for(int i=0;i<anslist.size();i++){
		cout<<anslist[i].name<<anslist[i].num<<anslist[i].sum<<endl;
		
	}

	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值