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;
}