CF786B Legacy

大致题意:给一个图,有3种边,t=1时,是点u对点v的单向边,t=2时,是点u到标号为[l,r]的点的单向边,t=3时,是标号为[l,r]到点u的边,求单源多汇最短路。


注意,点的数量为10^5,所以如果把每个点之间的边都存下来会占用GB级别的内存,显然这不是出题者所希望看到的,我们应该对存储边的方式进行调整。

既然我们不能把每个点对点的边都存下来,不如新建一些集散点用进行集中和分散,就像现实生活中的货运集散点一样,这样的话边的数量就会有所减少。

观察题目给出边的特点,它虽然给出的边是一个点指向多个点的边,但是这些点的边都标号都是连续的。所以把标号相邻的点联向一个共同的集散点,然后将二者共同的边改为从这个集散点联向其他点,这样将会稳定且有效地减少边的数量。

但是对于新图,边数仍然不少,但我们仍然可以对新建的点重复上述步骤来增加集散点,直到所有点都联向了一个集散点。

注意,入边和出边的集散点应该分开来建。

在纸上模拟上述步骤,会发现这不就是两颗线段树吗?对,它的确和线段树相差无几。所以我们可以用线段树的建树函数和更新过程来进行构建新图。之于最短路就不是本题的主要问题了。

#include <bits/stdc++.h>
#define maxn 1700000
#define ll long long
#define mp make_pair
#define pb push_back
#define st first
#define ed second
using namespace std;
inline void read(int &x) {
    char ch;
    bool flag = false;
    for (ch = getchar(); !isdigit(ch); ch = getchar())if (ch == '-') flag = true;
    for (x = 0; isdigit(ch); x = x * 10 + ch - '0', ch = getchar());
    x = flag ? -x : x;
}
inline void write(int x) {
    static const int maxlen = 100;
    static char s[maxlen];
    if (x < 0) {   putchar('-'); x = -x;}
    if (!x) { putchar('0'); return; }
    int len = 0; for (; x; x /= 10) s[len++] = x % 10 + '0';
    for (int i = len - 1; i >= 0; --i) putchar(s[i]);
}


set< pair<ll, int> > s;
vector < pair<int, int> > v[maxn];

int n, m, st;
ll dist[maxn];
int num[maxn][2], tot;
//x=0代表入点,x=1代表出点
int build(int p, int l, int r, int x) {
    if (l == r)
        return num[p][x] = l;
    num[p][x] = ++tot;
    int mid = (l + r) / 2;
    int ls = build(p * 2, l, mid, x);
    int rs = build(p * 2 + 1, mid + 1, r, x);
    if (x == 0)
    {
        v[num[p][x]].push_back(mp(ls, 0));
        v[num[p][x]].push_back(mp(rs, 0));
    }
    else
    {
        v[ls].push_back(mp(num[p][x], 0));
        v[rs].push_back(mp(num[p][x], 0));
    }
    return num[p][x];
}


void update(int p, int l, int r, int a, int b, int x, int y, int op) {
    if ((l == a) && (r == b))
    {
        if (op == 0)
            v[x].push_back(mp(num[p][op], y));
        else
            v[num[p][op]].push_back(mp(x, y));
        return ;
    }
    int mid = (l + r) / 2;
    if (b <= mid)
        update(p * 2, l, mid, a, b, x, y, op);
    else if (a > mid)
        update(p * 2 + 1, mid + 1, r, a, b, x, y, op);
    else
    {
        update(p * 2, l, mid, a, mid, x, y, op);
        update(p * 2 + 1, mid + 1, r, mid + 1, b, x, y, op);
    }
}




int main() {
    memset(dist, -1, sizeof(dist));
    read(n); read(m); read(st);
    tot = n;
    build(1, 1, n, 0);
    build(1, 1, n, 1);
    for (int i = 1; i <= m; i++)
    {
        int t;
        read(t);
        if (t == 1)
        {
            int a, b, c;
            read(a); read(b); read(c);
            v[a].pb(make_pair(b, c));
        }
        else
        {
            int v, l, r, w;
            scanf("%d%d%d%d", &v, &l, &r, &w);
            update(1, 1, n, l, r, v, w, t - 2);
        }
    }
    s.insert(mp(0, st));
    while (!s.empty())
    {
        ll y = s.begin()->st, x = s.begin()->ed;
        s.erase(s.begin());
        if (dist[x] != -1)
            continue;
        dist[x] = y;
        for (int i = 0; i < v[x].size(); i++)
            if (dist[v[x][i].st] == -1)
                s.insert(mp(1ll * v[x][i].ed + dist[x], v[x][i].st));
    }
    for (int i = 1; i <= n; i++)
        printf("%I64d ", dist[i]);
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Wireshark Legacy是Wireshark的一个版本,它是一个开源的网络协议分析工具,用于捕获和分析网络数据包。Wireshark Legacy可以帮助用户深入了解网络通信过程,识别和解决网络问题。 使用Wireshark Legacy,您可以: - 捕获网络数据包:Wireshark Legacy可以在网络接口上捕获传输的数据包,以便进行后续分析。 - 分析网络流量:Wireshark Legacy提供了强大的过滤和搜索功能,可以根据各种条件过滤和分析网络流量。 - 解码协议:Wireshark Legacy支持多种协议的解码,包括TCP、UDP、HTTP、DNS等,可以将数据包解码为易于理解的格式。 - 进行网络故障排除:Wireshark Legacy可以帮助您识别网络故障的原因,例如延迟、丢包、错误配置等。 - 分析安全问题:Wireshark Legacy可以帮助您检测和分析网络中的安全问题,例如恶意软件、网络攻击等。 对于Wireshark Legacy的使用,您可以按照以下步骤进行操作: 1. 下载和安装:您可以从Wireshark官网的下载页面(https://www.wireshark.org/#download)选择适合您操作系统的版本,并按照安装向导进行安装。 2. 打开Wireshark Legacy:安装完成后,您可以打开Wireshark Legacy应用程序。 3. 选择网络接口:在Wireshark Legacy的界面中,您可以选择要捕获数据包的网络接口。 4. 开始捕获数据包:点击“开始”按钮,Wireshark Legacy将开始捕获网络数据包。 5. 分析数据包:捕获到数据包后,您可以使用Wireshark Legacy的过滤和搜索功能来分析数据包,查找特定的信息或问题。 6. 解码协议:Wireshark Legacy会自动解码捕获到的数据包,并将其显示为易于理解的格式。 7. 导出和保存数据包:如果需要,您可以将捕获到的数据包导出为文件,以便后续分析或共享。 请注意,Wireshark Legacy是Wireshark的旧版本,建议您使用最新版本的Wireshark以获得更好的功能和性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值