zoukankan      html  css  js  c++  java
  • luogu2387 [NOI2014]魔法森林

    link

    显然满足的条件是一个偏序关系

    我们把所有边权按照a排序,按a从小到大顺序加边

    然后我们发现b上的问题就是一个动态最小瓶颈生成树问题,刚好可以用动态树维护

    代码暂时还没写

    upd:代码写完了

    第一次写的时候tmd nroot写错了。。。

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    int n, m;
    int ch[150010][2], fa[150010], st[150010], pos[150010], val[150010];
    bool lazy[150010];
    int u[150010], v[150010];
    struct edge { int x, y, a, b; } a[100010];
    
    void chkmin(int &a, int b) { if (a > b) a = b; }
    int ans = 0x3f3f3f3f, tot;
    
    bool nroot(int x) { return ch[fa[x]][1] == x || ch[fa[x]][0] == x; }
    void rev(int x) { swap(ch[x][0], ch[x][1]), lazy[x] ^= 1; }
    
    void pushup(int x)
    {
    	if (val[pos[ch[x][0]]] < val[pos[ch[x][1]]]) pos[x] = pos[ch[x][1]];
    	else pos[x] = pos[ch[x][0]];
    	if (val[x] > val[pos[x]]) pos[x] = x;
    }
    
    void pushdown(int x)
    {
    	if (lazy[x] == 1)
    	{
    		if (ch[x][0]) rev(ch[x][0]);
    		if (ch[x][1]) rev(ch[x][1]);
    		lazy[x] = 0;
    	}
    }
    
    void rotate(int x)
    {
    	int y = fa[x], z = fa[y];
    	int k = ch[y][1] == x, w = ch[x][k ^ 1];
    	if (nroot(y)) ch[z][ch[z][1] == y] = x;
    	ch[x][k ^ 1] = y, ch[y][k] = w;
    	if (w) fa[w] = y;
    	fa[y] = x, fa[x] = z;
    	pushup(y), pushup(x);
    }
    
    void splay(int x)
    {
    	int y = x, top = 0;
    	st[++top] = y;
    	while (nroot(y)) st[++top] = y = fa[y];
    	while (top > 0) pushdown(st[top--]);
    	while (nroot(x))
    	{
    		int y = fa[x], z = fa[y];
    		if (nroot(y)) rotate((ch[y][1] == x) ^ (ch[z][1] == y) ? x : y);
    		rotate(x);
    	}
    	pushup(x);
    }
    
    void access(int x)
    {
    	for (int y = 0; x > 0; x = fa[y = x])
    		splay(x), ch[x][1] = y, pushup(x);
    }
    
    void makeroot(int x)
    {
    	access(x), splay(x), rev(x);
    }
    
    int findroot(int x)
    {
    	access(x), splay(x);
    	while (ch[x][0])
    		pushdown(x), x = ch[x][0];
    	return x;
    }
    
    void split(int x, int y)
    {
    	makeroot(x), access(y), splay(y);
    }
    
    void link(int x, int y)
    {
    	makeroot(x);
    	if (findroot(y) != x) fa[x] = y;
    }
    
    void cut(int x, int y)
    {
    	makeroot(x);
    	if (findroot(y) == x && fa[x] == y && ch[x][1] == 0)
    		ch[y][0] = fa[x] = 0, pushup(y);
    }
    
    int main()
    {
    	scanf("%d%d", &n, &m); tot = n;
    	for (int i = 1; i <= m; i++) scanf("%d%d%d%d", &a[i].x, &a[i].y, &a[i].a, &a[i].b);
    	sort(a + 1, a + 1 + m, [](const edge &a, const edge &b) { return a.a < b.a; });
    	for (int i = 1; i <= m; i++)
    	{
    		makeroot(a[i].x);
    		if (findroot(a[i].y) == a[i].x)
    		{
    			if (val[pos[a[i].y]] > a[i].b)
    			{
    				int p = pos[a[i].y];
    				cut(p, u[p]);
    				cut(p, v[p]);
    				p = ++tot;
    				u[p] = a[i].x;
    				v[p] = a[i].y;
    				val[p] = a[i].b;
    				pos[p] = p;
    				link(p, u[p]);
    				link(p, v[p]);
    			}
    		}
    		else
    		{
    			int p = ++tot;
    			u[p] = a[i].x;
    			v[p] = a[i].y;
    			val[p] = a[i].b;
    			pos[p] = p;
    			link(p, u[p]);
    			link(p, v[p]);
    		}
    		makeroot(1);
    		if (findroot(n) == 1)
    			chkmin(ans, val[pos[n]] + a[i].a);
    	}
    	printf("%d
    ", ans == 0x3f3f3f3f ? -1 : ans);
    	return 0;
    }
    
  • 相关阅读:
    Java 数组
    【转】Centos 设置IP地址的几种方式
    【转】CentOS 使用yum命令安装出现错误提示”could not retrieve mirrorlist http://mirrorlist.centos.org ***”
    【转】CentOS图形界面的开启与关闭
    【转】linux Centos 6.5 安装桌面环境GNOME
    VirtualBox 更改主机和虚拟机之间的鼠标切换热键
    【转】Virtualbox虚拟机配置安装CentOS 6.5图文教程
    0622 python 基础05
    0617 python 基础04
    0610 python 基础03
  • 原文地址:https://www.cnblogs.com/oier/p/10385953.html
Copyright © 2011-2022 走看看