• POJ3417 Network


    一道LCA+树上差分

    原题链接

    显然每一条新增边都会导致环。
    如果试着举些例子的话,很容易发现割掉非环上的边,则割掉其他任意一条新增边都可达成目标;若割掉的原有边是一个环上的边,那么只有割掉导致这个环出现的新增边才能使得图变为不连通的两部分。若割掉的边是两个或两个以上的环上的边,那么无论第二次怎么割都不可能达成目标。
    也就是说,我们只要统计每一条原有边是几个环上的边,就可以直接枚举并计算方案个数。
    可以直接通过树链剖分暴力计算,但这里我们可以用针对边的树上差分来解决,且跑的更快。
    枚举每条新增边,设两端点为(x,y),则我们给节点(x,y)的权值加上(1),对节点(LCA(x,y))的权值减去(2)。枚举完毕后用(dfs)求出(f[x]),表示以(x)为根的子树中所有节点的权值之和,而最后的(f[x])实际上表示(x)与它父亲节点的这条边是几个环上的边,然后枚举所有原有边并统计答案即可。
    (LCA)部分可以使用(tarjan),跑的更快些。

    #include<cstdio>
    using namespace std;
    const int N = 1e5 + 10;
    struct eg {
    	int x, y;
    };
    eg a[N];
    struct dd {
    	int y, nex, id;
    };
    dd q[N << 1];
    int fi[N], di[N << 1], ne[N << 1], f[N], fi_q[N], an[N], v[N], fa[N], l, lq;
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c<'0' || c>'9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0'&&c <= '9'; c = getchar())
    		x = x * 10 + (c - '0');
    	return p ? -x : x;
    }
    inline int fin(int x)
    {
    	if (!(fa[x] ^ x))
    		return x;
    	return fa[x] = fin(fa[x]);
    }
    inline void add(int x, int y)
    {
    	di[++l] = y;
    	ne[l] = fi[x];
    	fi[x] = l;
    }
    inline void add_q(int x, int y, int z)
    {
    	q[++lq].y = y;
    	q[lq].nex = fi_q[x];
    	q[lq].id = z;
    	fi_q[x] = lq;
    }
    void tarjan(int x)
    {
    	int i, y;
    	v[x] = 1;
    	for (i = fi[x]; i; i = ne[i])
    	{
    		y = di[i];
    		if (!v[y])
    		{
    			tarjan(y);
    			fa[y] = x;
    		}
    	}
    	for (i = fi_q[x]; i; i = q[i].nex)
    	{
    		y = q[i].y;
    		if (!(v[y] ^ 2))
    			an[q[i].id] = fin(y);
    	}
    	v[x] = 2;
    }
    void dfs(int x, int fa)
    {
    	int i, y;
    	for (i = fi[x]; i; i = ne[i])
    	{
    		y = di[i];
    		if (y != fa)
    		{
    			dfs(y, x);
    			f[x] += f[y];
    		}
    	}
    }
    int main()
    {
    	int i, n, m, x, y, s = 0;
    	n = re();
    	m = re();
    	for (i = 1, fa[n] = n; i < n; i++)
    	{
    		fa[i] = i;
    		x = re();
    		y = re();
    		add(x, y);
    		add(y, x);
    	}
    	for (i = 1; i <= m; i++)
    	{
    		a[i].x = re();
    		a[i].y = re();
    		if (!(a[i].x^a[i].y))
    			an[i] = a[i].x;
    		add_q(a[i].x, a[i].y, i);
    		add_q(a[i].y, a[i].x, i);
    	}
    	tarjan(1);
    	for (i = 1; i <= m; i++)
    	{
    		f[a[i].x]++;
    		f[a[i].y]++;
    		f[an[i]] -= 2;
    	}
    	dfs(1, 0);
    	for (i = 2; i <= n; i++)
    	{
    		if (!f[i])
    			s += m;
    		else
    			if (!(f[i] ^ 1))
    				s++;
    	}
    	printf("%d", s);
    	return 0;
    }
    
  • 相关阅读:
    html中的背景图片不能充满整个浏览器 .
    linux系统安装Memcache
    linux下如何查看某软件是否已安装
    Redis监控之redisstat安装与详解
    memcached出现:Fatal error: Call to undefined method Memcached::connect()
    PHP多进程开发与Redis结合实践
    关于大型asp.net应用系统的架构架构的选择(转载)
    浅谈https\ssl\数字证书
    利用Lucene.net对附件做搜索(转载)
    Mic's blog iis下ISAPI_Rewrite配置及 iis rewrite 规则书写
  • 原文地址:https://www.cnblogs.com/Iowa-Battleship/p/9574890.html
Copyright © 2020-2023  润新知