计蒜客2020.7.27 H.Knights Airways (优先队列+拓扑排序)

题意:

有很多航班,为了让所有人都能赶上航班,所以如果存在航班 a -> b , b -> c ,那么后一个航班必须等待第一个航班飞到目的地后一个航班才能起飞。容易发现这存在着前后关系,需要用拓扑排序,但是呢,题目给出了每一个航班的班号,对于没有前后这种等待关系的航班则先输出航班号小的,有这种前后关系则先输出需要先起飞的航班号。这就需要我们用一个优先队列来代替普通的队列来实现拓扑排序,对于每一个航班的出发地和目的地(我这里为了练手专门写了一下Trie树)都需要对应到数字,这样才能建图,在拓扑排序中将某个点的邻接点和这条边的权值(航班号)看做一个整体(按照航班号小的优先),然后就是排序了。

再说一下,在这里呢,对于一开始入度为0的点就显然没有排序的必要了,只需要将入度为0的点的邻接点和边权压入优先队列就可以了。

code:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <sstream>
#include <cstring>
#include <set>
#include <cctype>
#include <bitset>
#define IO                       \
    ios::sync_with_stdio(false); \
    // cin.tie(0);                  \
    // cout.tie(0);
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int maxn = 1e5 + 100;
const int maxm = 16 + 10;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const LL mod = 1e9 + 7;
int dis[8][2] = {0, 1, 1, 0, 0, -1, -1, 0, 1, -1, 1, 1, -1, 1, -1, -1};
typedef struct Node
{
    bool isword;
    int id;
    Node *next[maxm];
} Trie;
struct Edge
{
    int next, to, plane_id;
} e[maxn];
typedef struct NODE
{
    int u, id;
    bool operator<(const NODE &a) const
    {
        return id > a.id;
    }
} node;
int head[maxn], k, pnum = 0;
int in[maxn];
bool vis[maxn];
void add(int u, int v, int pid)
{
    e[k].next = head[u];
    e[k].to = v;
    e[k].plane_id = pid;
    head[u] = k++;
}
int insert(Trie *root, string s)
{
    int n = s.size();
    Trie *p = root;
    for (int i = 0; i < n; i++)
    {
        if (p->next[s[i] - 'A'] == NULL)
        {
            Trie *node = new Trie;
            node->isword = false;
            for (int j = 0; j < maxm; j++)
                node->next[j] = NULL;
            p->next[s[i] - 'A'] = node;
        }
        p = p->next[s[i] - 'A'];
    }
    if (p->isword)
        return p->id;
    else
    {
        p->isword = true;
        p->id = ++pnum;
        return p->id;
    }
}
void topo(int node_num, int edge_num)
{
    priority_queue<node> q;
    for (int i = 1; i <= node_num; i++)
    {
        if (!in[i])
        {
            for (int j = head[i]; j != -1; j = e[j].next)
                q.push({e[j].to, e[j].plane_id});
        }
    }
    while (!q.empty())
    {
        node now = q.top();
        q.pop();
        in[now.u]--;
        cout << now.id;
        edge_num--;
        if (edge_num)
            cout << " ";
        if (!in[now.u])
        {
            for (int i = head[now.u]; i != -1; i = e[i].next)
            {
                int v = e[i].to;
                q.push({v, e[i].plane_id});
            }
        }
    }
    return;
}
int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
#endif
    IO;
    int T, n;
    cin >> T;
    while (T--)
    {
        k = 0;
        pnum = 0;
        memset(head, -1, sizeof head);
        memset(in, 0, sizeof in);
        Trie *root = new Trie;
        root->isword = false;
        for (int i = 0; i < maxm; i++)
            root->next[i] = NULL;
        cin >> n;
        int maxv = -1;
        for (int i = 0; i < n; i++)
        {
            string s1, s2;
            int id;
            cin >> s1 >> s2 >> id;
            int x = insert(root, s1);
            int y = insert(root, s2);
            maxv = max(maxv, x);
            maxv = max(maxv, y);
            in[y]++;
            add(x, y, id);
        }
        topo(maxv, n);
        cout << "\n";
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44115065/article/details/107703140