蓝桥杯 卡勒沃夫之弱水路三千(拓扑+map)

题目描述:

锦瑟年华谁与度 莫问情归处 只影向斜阳 剑吼西风 欲把春留驻

天涯芳草无归路 回首花无数 解语自销魂 弱袂萦春 尘缘不相误

在卡勒沃夫充满文学杀伤力的声音中,身处紫荆2号楼202B的四位远近高低各不同的室友纷纷回忆起了各自波澜起伏的过去,并对长在百草园,邻有百花谷的现状表达了各自的见解。

某Q:"…我小学就开窍了…她的父母说我很好,但是…今天又和北林的联系了…"

某X:"…差点就成了,结果到学校了…这个方法放假了我去对我的同桌用!…"

某W:"…"(千言万语不言中,有大量的故事等待考古)

某Z:"…为了来清华…咱们审美观不一样,不会抢…"

卡勒沃夫在这个不朽的夜话中搜集出了某人零散的历任女友资料,为了强迫某人将他出的题目的标程交出,现在卡勒沃夫需要一个能将这些零散信息整合起来的程序。伴随着雄壮委婉动人的音乐,身为程序设计快男(超女)的你降临了!卡勒沃夫正对着您做Orz状并请求着:“神牛啊!请施舍给我一段程序把!偶米头发~!”。

输入:

第一行为一个不超过5的整数T,表示数据的组数。之后每组数据的一行为一个不超过100的整数n。之后n行每行有两个用单个空格隔开的字符串(每个字符串只有英文大小写字母,长度不超过10),为两位mm的名字。每行第一个mm先于第二个mm成为某人的女友。

在这里我们假装诅咒某人不会同时被两个或两个以上mm泡,某个mm抛弃了某人后不会再吃回头草,同时卡勒沃夫深邃的洞察力使得他收集到了充足的信息以确定某人女友的先后顺序。

在小数据组中出现的人物不超过13个

输出:

输出T行,每行对应一组数据,每组测试数据字符串两两之间用空格隔开,最后一个字符串后无空格。并按照m们从先到后成为某人女友的顺序输出她们的名字,各个名字间用一个空格隔开。

输入样例:

2
2
RY Unknown
YSZ RY
3
tomorrow yestoday
tomorrow today
today yestoday

输出样例:

YSZ RY Unknown
tomorrow today yestoday

思路:

这是一道比较裸的拓扑排序题,根据题意可以判断出所有mm所构成的图是一个有向无环图,故可以想到用拓扑。
PS:但是最开始,我天真的以为用个链表就可以解决了(小声),感谢队友大大怪和呵呵的先生的指点!!!
做题的时候我遇到的主要的难点在于,如何将字符串映射到图里,并且进行拓扑排序。一开始也用的map,但是由于使用的不够熟练,debug了好久。最终参考了下面一篇大大文章中用map构建邻接表的方法。感谢!!!
蓝桥杯 算法提高 卡勒沃夫之弱水路三千(提高型)

审题的时候应该注意输出格式,每一行的末尾不能有空格!

代码如下:
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);

using namespace std;


const int N = 110;

map<string, vector<string>> h; //储存邻接表
map<string, int> d; //记录入度
map<string, int> mark; //标记是否已经在图内

vector<string> ans; //储存答案

void Clear()
{
    h.clear(), d.clear(), mark.clear(), ans.clear(); //快乐初始化
}

void add(string a, string b) //构建有向无环图
{
    //应注意每次都要访问一下元素是否已经存在于图中,以免出现重复元素
    if(!mark.count(a))
    {
        d[a] = 0;
        mark[a]++;
    }
    if(!mark.count(b))
    {
        d[b] = 0;
        mark[b]++;
    }
    h[a].push_back(b);
    d[b] ++;
}

void topsort()
{
    queue<string> q;

    for(map<string, int>::iterator it = d.begin(); it != d.end(); ++it)
        if(it->second == 0)
        {
            q.push(it->first);
            ans.push_back(it->first);
        }

    while(q.size())
    {
        auto t = q.front();
        q.pop();

        for(int i = 0; i < h[t].size(); i++)
        {
            d[h[t][i]]--;
            if(!d[h[t][i]])
            {
                q.push(h[t][i]);
                ans.push_back(h[t][i]);
            }
        }
    }
}

int main()
{
    IOS;

    int t;

    cin >> t;

    while(t--)
    {
        Clear();

        int n;
        cin >> n;

        for(int i = 0; i < n; i++)
        {
            string s1, s2;
            cin >> s1 >> s2;
            add(s1, s2);
        }

        topsort();

        for(int i = 0; i < ans.size() - 1; i++) cout << ans[i] << " ";
        cout << ans[ans.size() - 1] << endl; //注意输出格式
    }

    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值