hdu 4039 暴力 The social network

题意:给出N对好友关系,之后Q次提问,问可以对该用户推荐的相识度最高的好友;

解:

     纯暴力啊。第一次写又是T又是CE又是RE的,没办法了。重新搞一遍。用了十多分钟重写了一遍,然后重新交了,WA了,还好没T。昨天晚上改了改初始化,还是没过。今天早上看了一遍,将初始化向量的n改成了 2 * n,找不出错了,就交了。神一般地过了。一样的思路,我觉得基本一样的代码,为什么第一次的T了呢。。。。

    一样的思路,写得好差还是有区别的(虽然我觉得我写得一样)。 还是初始化很重要啊!!!

   还想用字典树写一遍,鉴于没时间学那么多。我先捡重要的写了先,这个有空再写吧。后面先贴个字典树的代码。

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#include <map>

using namespace std;
int n,Q,T,sub;
char na[100],nb[100];
map <string,int> na_no;
map <int,string> no_na;
queue <int > q;
vector <int > v[2001];
string name[2001];
bool vis[2001];
int cishu[2001],subname;
void bfs(int sr){
    memset(vis,false,sizeof(vis));
    memset(cishu,0,sizeof(cishu));
    subname =0;
    vis[sr] = true; int tmp;
    while(!q.empty()) q.pop();

    for(int j = 0 ; j < v[sr].size(); j ++){
        tmp = v[sr][j];//儿子
        if(!vis[tmp]) q.push(tmp),vis[tmp] = true;
    }
    while(!q.empty()){
        tmp = q.front(); q.pop();
        for(int j = 0; j < v[tmp].size(); j ++){
            int tmp2 = v[tmp][j];//孙子
            if(!vis[tmp2])  cishu[tmp2] ++;
        }
    }

    int Max = 0;
    for(int j = 1; j <= sub; j ++){
        if(cishu[j] > Max)
            Max = cishu[j];
    }
    if(Max == 0 ) {
        printf("-\n");
        return ;
    }
    for(int j = 1; j <= sub; j ++){
        if(cishu[j] == Max ){
            name[subname ++] = no_na[j];
        }
    }
    if(subname == 0 ) {
        printf("-\n");
        return ;
    }
    sort(name,name + subname);
    for(int j = 0; j < subname - 1; j ++)
        printf("%s ",name[j].c_str()); printf("%s\n",name[subname - 1].c_str());
}
int main(){
    scanf("%d",&T);
    for(int ca = 1; ca <= T; ca ++){
        scanf("%d%d",&n,&Q);
        printf("Case %d:\n",ca);
        sub = 0;
        na_no.clear();  no_na.clear();
        for(int i = 1; i <= 2 * n; i ++)    v[i].clear();//初始化的问题要特别小心

        for(int i = 1; i <= n;i ++){
            scanf("%s%s",na,nb);
            if(na_no[na] == 0){
                na_no[na] = ++sub;
                no_na[sub] = na;
            }
            if(na_no[nb] == 0){
                na_no[nb] = ++sub;
                no_na[sub] = nb;
            }
            int a = na_no[na];
            int b = na_no[nb];
            v[a].push_back(b);
            v[b].push_back(a);
        }
//        for(int i = 1; i  <= sub; i ++)
//            printf("%d   %s\n",i, no_na[i].c_str());

        for(int i = 0; i < Q; i ++){
            scanf("%s",na);
            bfs(na_no[na]);
        }
    }
    return 0;
}
首先对所有用户的名字(字符串)标号,好处理一些,这里用了字典树实现了;
接下来,用邻接矩阵表示任意俩个用户直接的关系,再者,对与每一次询问,遍历该用户所有好友的好友,找出出现次数最多的;
最后,若有多个推荐好友时,要字典树输出,额,我用优先队列做了,重载操作符,之后直接丢进去,再输出就可以了

转自:http://www.cnblogs.com/nanke/archive/2011/09/12/2173990.html

#include<iostream>
#include<string>
#include<queue>
using namespace std;
int num;
short map[2001][2001];
struct str
{
    char s[16];
    friend bool operator<(const str ne1,const str ne2)//重载操作符
    {
        if(strcmp(ne1.s,ne2.s)==1)
            return true;
         return false;
    }
}st[2001];
typedef struct node  
{  
    int cnt;  
    struct node *next[26]; 
}*tree,Trie;  
tree root; 
int ex[2001],f[2001];
inline int GetNum(char *t)//用字典树对字符串编号
{
    tree p = root,newnode;
    for(int i = 0;i < strlen(t); ++i){
        int u = t[i] - 'a';
        if(p->next[u]==NULL)
        {    
            newnode=(tree)malloc(sizeof(Trie));
            newnode->cnt=-1;
            for(int j=0;j<26;j++)
                newnode->next[j]=NULL;
            p->next[u]=newnode;
            p=newnode;
        }
        else
        p = p->next[u];
    }
    if(p->cnt == -1) //该节点未出现过
        p->cnt = num ++;
    return p->cnt;
}
int main()
{
    int T=0,cas,n,q,n1,n2;
    char str1[16],str2[16];
    scanf("%d",&cas);
    while(cas--)
    {    
        root=(tree)malloc(sizeof(Trie));
        root->cnt=-1;
        for(int j=0;j<26;j++)
          root->next[j]=NULL;
        num=0;
        scanf("%d %d",&n,&q);
        memset(map,0,sizeof(map));
        for(int i=0;i<n;i++)
        {
            scanf("%s %s",str1,str2);
            n1=GetNum(str1);
            n2=GetNum(str2);
            strcpy(st[n1].s,str1);
            strcpy(st[n2].s,str2);
            map[n1][n2]=map[n2][n1]=1;
        }
        printf("Case %d:\n",++T);
        while(q--)
        {
            int max=0,count=0;
            memset(f,0,sizeof(f));
            memset(ex,0,sizeof(ex));
            scanf("%s",str1);
            n1=GetNum(str1);
            for(int i=0;i<num;i++)
            {
                if(n1==i)continue;//自己跟自己,肯定……
                if(map[n1][i]==1)
                {
                    for(int j=0;j<num;j++)
                    {
                        if(i==j||j==n1)continue;//推荐好友本身不能是自己的好友
                        if(!map[n1][j]&&map[i][j]==1)
                        {
                            ex[j]++;
                            if(ex[j]>=max)
                            {
                                if(ex[j]==max)//若有出现次数相同的,累加
                                    f[count++]=j;
                                else {
                                    count=0;//若有出现次数更多的,直接覆盖
                                    f[count++]=j;
                                }
                                max=ex[j];
                            }
                        }
                    }
                }
            }
            priority_queue<str> Q;
            if(count==0) printf("-");
            else
            {
                for(int i=0;i<count;i++)
                    Q.push(st[f[i]]);
            }
            for(int i=0;i<count;i++)
            {
                if(i==0)
                printf("%s",Q.top().s);
                else 
                printf(" %s",Q.top().s);
                Q.pop();
            }
            printf("\n");
       }
    }
        return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值