Pat1034

这题的话其实不是特别难,但是如果没有特别好的方法,很难拿到满分,而且比较麻烦,但是会一点小小的搜索,拿个十几分还是可以的,比较恶心的题目没有告诉你有多少个点,如果map的话,最多就2000个不同的点,因为它只给你1000条边,我第一次看到这题想到的是搜索,搜的一塌糊涂,拿了17分,后来看到王道上的人都是用并查集做的,所以自己也试了下并查集的做法,这题用并查集能较好的解决2个问题:1在并查集选择father时,优化了的并查集选择树儿子较多的为father,这题可以选择通信量较大的为father 2如何计算一个集合的总通信量,只要枚举每条边,找到这条边属于哪个father,把相应的值加上就好。用搜索的话,个人还是没有拿到满分,这里代码就不献丑了,

并查集代码如下:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<string>
#include<map>
#include<algorithm>
#define N 2001
using namespace std;
map<string,int>cl;
struct node
{
    string st,ed;
    int d;
}e[N];
int fa[N];
int num[N];
int tot[N];
int t[N];
struct ans
{
    string aa;
    int bb;
}ans[N];
int getfather(int x)
{
	if (fa[x] != x)
		fa[x]=getfather(fa[x]);
	return fa[x];
}
void un(int a, int b)
{
    a = getfather(a);
    b = getfather(b);
    if(a==b)
    return;
    if(t[a]>t[b])
    {
        fa[b]=a;
        num[a]+=num[b];
    }
    else
    {
        fa[a]=b;
        num[b]+=num[a];
    }
}

int main()
{
	int n,m;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		int i,j;
		int vnum=0;
		cl.clear();
		for(i=1;i<=n;i++)
		{
            string a,b;
            int t;
            cin >> a >> b >> t;
            e[i].st = a;
            e[i].ed = b;
            e[i].d = t;
		    if(cl.count(e[i].st)==0)
		    {
                ++ vnum;
                cl.insert(make_pair(e[i].st,vnum));
            }
            if(cl.count(e[i].ed)==0)
		    {
                ++ vnum;
                cl.insert(make_pair(e[i].ed,vnum));
            }
        }
        for (i=1;i<=vnum;i++)
        {
            fa[i] = i;
            t[i] = 0;
            tot[i] = 0;
            num[i] = 1;
        }
		for(i=1;i<=n;i++)
		{
            t[cl[e[i].st]]+=e[i].d;
            t[cl[e[i].ed]]+=e[i].d;
        }
        for(i=1;i<=n;i++)
        un(cl[e[i].st],cl[e[i].ed]);
        
        for(i=1;i<=vnum;i++)
        fa[i]=getfather(i);
        
		for(i=1;i<=n;i++)
		{
	       int father=getfather(cl[e[i].st]);
            tot[father]+=e[i].d;
        }
        int cnt=0;
        for (map<string,int>::iterator it = cl.begin();it != cl.end(); it++)
        {
            int kk=it->second;
            if(tot[kk]>m&&num[kk]>=3&&fa[kk]==kk)
            {
                ans[++cnt].aa=it->first;
                ans[cnt].bb=num[kk];
            }
        }
        printf("%d\n",cnt);
        for(i=1;i<=cnt;i++)
        cout<<ans[i].aa<<" "<<ans[i].bb<<endl;
    }
    return 0;
}

你可能感兴趣的:(搜索,map,并查集)