zoukankan      html  css  js  c++  java
  • poj3471

    题意:一张n节点连通无向图,n-1条树边,m条非树边。若通过先删一条树边,再删一条非树边想操作   

    将此图划分为不连通的两部分,问有多少种方案。

     

     利用LCA整好区间覆盖,dfs用来求前缀和

    需要注意的是,覆盖数为1的时候才可以选择哦!

    覆盖数为0,代表可以直接拆开

    最后附上一张我老婆

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #define maxn 110000
    using namespace std;
    typedef long long ll;
    int dp[maxn][33];
    int dep[maxn];
    long long cnt[maxn];//差分数组
    int head[450100];
    
    struct Node {
    	int to;
    	int next;
    }G[450100];
    int cnn = 1;
    void insert(int be, int en) {
    	G[cnn].to = en; G[cnn].next = head[be]; head[be] = cnn;;//头插法
    	cnn++;
    }
    
    void dfs(int u, int par) {
    	dep[u] = dep[par] + 1;
    	for (int i = 0; i <= 21; i++) {
    		dp[u][i + 1] = dp[dp[u][i]][i];
    	}
    	for (int i = head[u]; i; i = G[i].next) {
    		int p = G[i].to;
    		if (p == par) continue;
    		dp[p][0] = u;
    		dfs(p, u);
    	}
    	return;
    }
    int LCA(int x, int y) {
    	if (dep[x] < dep[y]) swap(x, y);//x在下面
    	for (int i = 20; i >= 0; i--) {
    		if (dep[dp[x][i]]  >= dep[y]) x = dp[x][i];
    		if (x == y) return x;
    	}
    	
    	for (int i = 20; i >= 0; i--) {
    		if (dp[x][i] != dp[y][i]) {
    			x = dp[x][i];
    			y = dp[y][i];
    		
    		}
    	}
    	
    	return dp[x][0];
    }
    int n, m;
    int find(int x,int par) {
    	
    	for (int i = head[x]; i; i = G[i].next) {
    		int p = G[i].to;
    		if (p == par) continue;
    		find(p, x);
    		cnt[x] += cnt[p];
    	}
    	
    	return 0;
    }
    int main() {
    	scanf("%d %d", &n, &m);
    	int be, en;
    	for (int i = 0; i < n - 1; i++) {
    		scanf("%d %d", &be, &en);
    		insert(be, en);
    		insert(en, be);
    	}
    	dp[1][0] = 1;
    	dfs(1, 0);
    	for(int i=0;i<m;i++) {
    		scanf("%d %d", &be, &en);
    		int p = LCA(be, en);
    		cnt[p] -= 2;
    		cnt[be]++;
    		cnt[en]++;
    	}
    	find(1, 0);
    	ll ans = 0;
    	
    	for (int i = 2; i <= n; i++) {
    		if (cnt[i] == 0) ans += m;//乘法原理
    		else if (cnt[i] == 1) ans++;
    	}
    	printf("%lld
    ", ans);
    	return 0;
    }
    

    寻找真正的热爱
  • 相关阅读:
    升级安装 Ubuntu 后该做的20项优化工作
    Delphi中点击DBGrid某一行获得其详细数据方法
    android eclipse xml不自动代码提示
    区别不同浏览器,CSS hack写法
    自我介绍
    秋季学期学习总结
    人生路上影响最大的三位老师
    SQL优化34条
    Visual Studio 2010将支持多种架构设计图
    Visual Studio 2010的SharePoint工作流功能
  • 原文地址:https://www.cnblogs.com/lesning/p/11448913.html
Copyright © 2011-2022 走看看