zoukankan      html  css  js  c++  java
  • codeforces786B Legacy 线段树优化建图

    网址:https://codeforces.com/problemset/problem/786/B

    题意:

    给出$n$个城市和三种路径:$u$向$v$连一条带权无向边;$[l,r]$向$v$连一条带权无向边;$u$向$[l,r]$连一条带权无向边,给出一个起点$s$,求它到其他点的最短路径,如果不能到达,输出$-1$。

    题解:

    现在有三种操作:点对点连边,点对线段连边,线段对点连边。且点数多达$1e5$,所以就要建立线段树优化建图。建立入度树(就是边的终点)时,需要连上父节点往子节点的点且边权为$0$,建立出度树时,需要子节点往父节点连上边权为$0$的边。然后这里点对点,区间对点,点对区间连边,所以可以直接连边不需要超级结点,如果出现了区间对区间,就需要超级结点。然后连边之后在这个图上用一次$dijkstra$算法就行了。

    AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MAXN = 5e5 + 5;
    struct node
    {
    	int l, r;
    };
    node tr[MAXN];
    struct edge
    {
    	int to;
    	ll w;
    	edge() {}
    	edge(int _to, ll _w) :to(_to), w(_w) {}
    	bool operator<(const edge& a)const
    	{
    		return w > a.w;
    	}
    };
    vector<edge>G[MAXN];
    int cnt = 0;
    void buildout(int& rt, int l, int r)
    {
    	if (l == r)
    	{
    		rt = l;
    		return;
    	}
    	rt = ++cnt;
    	int m = (l + r) >> 1;
    	buildout(tr[rt].l, l, m);
    	buildout(tr[rt].r, m + 1, r);
    	G[rt].push_back(edge(tr[rt].l, 0));
    	G[rt].push_back(edge(tr[rt].r, 0));
    }
    void buildin(int& rt, int l, int r)
    {
    	if (l == r)
    	{
    		rt = l;
    		return;
    	}
    	rt = ++cnt;
    	int m = (l + r) >> 1;
    	buildin(tr[rt].l, l, m);
    	buildin(tr[rt].r, m + 1, r);
    	G[tr[rt].l].push_back(edge(rt, 0));
    	G[tr[rt].r].push_back(edge(rt, 0));
    }
    void update(int rt, int l, int r, int ql, int qr, int v, int w, int type)
    {
    	if (l <= ql && r >= qr)
    	{
    		type == 2 ? G[v].push_back(edge(rt, w)) : G[rt].push_back(edge(v, w));
    		return;
    	}
    	int m = (ql + qr) >> 1;
    	if (l <= m)
    		update(tr[rt].l, l, r, ql, m, v, w, type);
    	if (r > m)
    		update(tr[rt].r, l, r, m + 1, qr, v, w, type);
    }
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    ll dis[MAXN];
    bool vis[MAXN];
    priority_queue<edge>Q;
    void dijkstra(int s)
    {
    	memset(vis, 0, sizeof(vis));
    	memset(dis, 0x3f, sizeof(dis));
    	dis[s] = 0;
    	Q.push(edge(s, dis[s]));
    	while (Q.size())
    	{
    		auto u = Q.top();
    		Q.pop();
    		if (vis[u.to])
    			continue;
    		vis[u.to] = 1;
    		for (auto i : G[u.to])
    		{
    			int v = i.to;
    			if (!vis[v] && dis[v] > dis[u.to] + i.w)
    			{
    				dis[v] = dis[u.to] + i.w;
    				Q.push(edge(v, dis[v]));
    			}
    		}
    	}
    }
    int rt1, rt2;
    int main()
    {
    	int n, m, s;
    	scanf("%d%d%d", &n, &m, &s);
    	cnt = n + 1;
    	buildin(rt2, 1, n);//区间出去
    	buildout(rt1, 1, n);//区间进来
    	int op, u, v, l, r, w;
    	while (m--)
    	{
    		scanf("%d", &op);
    		if (op == 1)
    		{
    			scanf("%d%d%d", &u, &v, &w);
    			G[u].push_back(edge(v, w));
    		}
    		else
    		{
    			scanf("%d%d%d%d", &v, &l, &r, &w);
    			update(op == 2 ? rt1 : rt2, l, r, 1, n, v, w, op);
    		}
    	}
    	dijkstra(s);
    	for (int i = 1; i <= n; ++i)
    		printf("%lld%c", dis[i] >= INF ? -1 : dis[i], i == n ? '
    ' : ' ');
    	return 0;
    }
    
  • 相关阅读:
    Linux基本网络设置(IP配置等,网卡驱动缓存,网卡中断)
    posix多线程有感线程高级编程(进程的优先级)
    posix多线程有感线程高级编程(均衡负载CPU绑定)
    posix多线程有感线程高级编程(线程调度以及优先级设置)
    linux多线程和锁
    posix多线程有感—sysconf系统变量
    Linux环境下获取网卡连接状态
    posix多线程有感线程高级编程(线程和fork,exec)
    posix多线程有感线程高级编程(线程堆栈)
    Day64:codeblocks安装 for Mac
  • 原文地址:https://www.cnblogs.com/Aya-Uchida/p/12324350.html
Copyright © 2011-2022 走看看