zoukankan      html  css  js  c++  java
  • POJ3417 Network

    题目链接

    翻译:一棵无根树,给出m条边,把这m条边连上,每次你能毁掉两条边,规定一条是树边,一条新边。问有多少种方案能使树断裂。


    这题想一想就明白了:考虑每一条新边连接的两个点(x)(y),对于这两点间树上路径的边,如果没有和其他新边连成环,那么这条边删了后树就会断裂,否则就断不了。所以每一次我们把(x)(y)在树上的路径标记一遍,最后统计每一条边的标记情况:如果没有标记,那么随时可以删;如果只标记了一次,那么必须和对应的新边一块删;如果被标记了多次,那么任何时刻都删不了。
    记被标记了0次、1次、多次的边的数量为(n1,n2,n3),那么答案就是(n1 * m + n2)


    至于边标记,那么就要用到树上差分,而且是边差分。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<queue>
    #include<assert.h>
    #include<ctime>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    #define forE(i, x, y) for(int i = head[x], y; ~i && (y = e[i].to); i = e[i].nxt)
    typedef long long ll;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    const int maxn = 1e5 + 5;
    const int N = 17;
    In ll read()
    {
    	ll ans = 0;
    	char ch = getchar(), las = ' ';
    	while(!isdigit(ch)) las = ch, ch = getchar();
    	while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
    	if(las == '-') ans = -ans;
    	return ans;
    }
    In void write(ll x)
    {
    	if(x < 0) x = -x, putchar('-');
    	if(x >= 10) write(x / 10);
    	putchar(x % 10 + '0');
    }
    In void MYFILE()
    {
    #ifndef mrclr
    	freopen(".in", "r", stdin);
    	freopen(".out", "w", stdout);
    #endif
    }
    
    int n, m;
    struct Edge
    {
    	int nxt, to;
    }e[maxn << 1];
    int head[maxn], ecnt = -1;
    In void addEdge(int x, int y)
    {
    	e[++ecnt] = (Edge){head[x], y};
    	head[x] = ecnt;
    }
    
    int fa[N + 2][maxn], dep[maxn];
    In void dfs(int now, int _f)
    {
    	for(int i = 1; (1 << i) <= dep[now]; ++i)
    		fa[i][now] = fa[i - 1][fa[i - 1][now]];
    	forE(i, now, v)
    	{
    		if(v == _f) continue;
    		dep[v] = dep[now] + 1, fa[0][v] = now;
    		dfs(v, now);
    	}
    }
    In int lca(int x, int y)
    {
    	if(dep[x] < dep[y]) swap(x, y);
    	for(int i = N; i >= 0; --i)
    		if(dep[fa[i][x]] >= dep[y]) x = fa[i][x];
    	if(x == y) return x;
    	for(int i = N; i >= 0; --i)
    		if(fa[i][x] != fa[i][y]) x = fa[i][x], y = fa[i][y];
    	return fa[0][x]; 
    }
    
    int a[maxn];
    ll ans = 0;
    In void dfs2(int now, int _f)
    {
    	forE(i, now, v)
    	{
    		if(v == _f) continue;
    		dfs2(v, now);
    		a[now] += a[v]; 
    	}
    	if(now == 1) return;
    	if(!a[now]) ans += m;
    	else if(a[now] == 1) ++ans;
    }
    
    int main()
    {
    //	MYFILE();
    	Mem(head, -1), ecnt = -1; 
    	n = read(), m = read();
    	for(int i = 1; i < n; ++i)
    	{
    		int x = read(), y = read();
    		addEdge(x, y), addEdge(y, x);
    	}
    	dep[1] = 1, dfs(1, 0);
    	for(int i = 1; i <= m; ++i)
    	{
    		int x = read(), y = read();
    		int z = lca(x, y);
    		a[x]++, a[y]++, a[z] -= 2;
    	}
    	dfs2(1, 0);
    	write(ans), enter;
    	return 0;	
    }
    
  • 相关阅读:
    How to convert VirtualBox vdi to KVM qcow2
    (OK)(OK) adb -s emulator-5554 shell
    (OK)(OK) using adb with a NAT'ed VM
    (OK) How to access a NAT guest from host with VirtualBox
    (OK) Creating manually one VMs from an existing VDI file in CLI (VBoxManage) in Fedora 23
    (OK)(OK) Creating VMs from an existing VDI file in CLI (VBoxManage) in Fedora 23
    (OK) Creating_VMs_from_an_existing_VDI_file.txt
    (OK) Creating VMs from an existing VDI file —— in OS X
    (OK) install_IBM_SERVER.txt
    (OK) install chrome & busybox in android-x86_64 —— uninstall chrome
  • 原文地址:https://www.cnblogs.com/mrclr/p/13764187.html
Copyright © 2011-2022 走看看