zoukankan      html  css  js  c++  java
  • COGS2434 暗之链锁

    【题目描述】


    传说中的暗之连锁被人们称为Dark。Dark是人类内心的黑暗的产物,古今中外的勇者们都试图打倒它。经过研究,你发现Dark呈现无向图的结构,图中有N个节点和两类边,一类边被称为主要边,而另一类被称为附加边。Dark有N – 1条主要边,并且Dark的任意两个节点之间都存在一条只由主要边构成的路径。另外,Dark还有M条附加边。

    你的任务是把Dark斩为不连通的两部分。一开始Dark的附加边都处于无敌状态,你只能选择一条主要边切断。一旦你切断了一条主要边,Dark就会进入防御模式,主要边会变为无敌的而附加边可以被切断。但是你的能力只能再切断

    Dark的一条附加边。现在你想要知道,一共有多少种方案可以击败Dark。注意,就算你第一步切断主要边之后就已经把Dark斩为两截,你也需要切断一条附加边才算击败了Dark。


    【输入格式】


    第一行包含两个整数N和M。

    之后N – 1行,每行包括两个整数A和B,表示A和B之间有一条主要边。

    之后M行以同样的格式给出附加边。


    【输出格式】

    输出一个整数表示答案。

    【样例输入】

    4 1

    1 2

    2 3

    1 4

    3 4

    【样例输出】

    3

    【提示】

    自己瞎做吧

    【数据范围】


    对于20% 的数据,N≤100,M≤100。

    对于100% 的数据,N≤100 000,M≤200 000。数据保证答案不超过2^31– 1。


    我们定义w[i]为第i个节点被虚边覆盖的次数(边权已下放),那么如果w[i]=1,Ans+=1,w[i]=0,Ans+=m;

    那么如何快速的求出w[i]?

    可以考虑用树上差分,对于虚边(u,v),对w[u]++,w[v]++,w[lca(u,v)]-=2;

    然后再进行一次dfs即可求出,那么正确性呢。

    对于(u,v)下面的点肯定没有影响,对于(u,lca(u,v))和(v,lca(u,v))上的点的权值增加1,到了lca(u,v)的地方权值恢复正常。

    那么就是树上差分了。

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 100005;
    int n,m,first[MAXN],e=1,deep[MAXN],w[MAXN],f[MAXN][18];
    long long Ans = 0;
     
     
    template<typename _t>
    inline _t read(){
    	_t x=0,f=1;
    	char ch=getchar();
    	for(;ch>'9'||ch<'0';ch=getchar())if(ch=='-')f=-f;
    	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+(ch^48);
    	return x*f;
    }
     
    struct edge{
    	int u,v,next;
    }a[MAXN<<1];
     
    void push(int u,int v){
    	a[e].u=u;
    	a[e].v=v;
    	a[e].next=first[u];
    	first[u]=e++;
    }
     
    void dfs(int u,int fa){
    	deep[u]=deep[fa]+1;
    	f[u][0]=fa;
    	for(int i=1;i<=17;i++)
    		f[u][i]=f[f[u][i-1]][i-1];
    	for(int i=first[u];i;i=a[i].next)
    		if(a[i].v!=fa)
    			dfs(a[i].v,u);
    }
     
    inline int lca(int u,int v){
    	if(deep[u]<deep[v])swap(u,v);
    	int t = deep[u]-deep[v];
    	for(int i=0;i<=17;i++)
    		if(t&(1<<i))
    			u=f[u][i];
    	if(u==v)return u;
    	for(int i=17;i>=0;i--)
    		if(f[u][i]!=f[v][i])
    			u=f[u][i],v=f[v][i];
    	return f[u][0];
    }
     
    void __dfs(int u){
    	for(int i=first[u];i;i=a[i].next)
    		if(a[i].v!=f[u][0])
    			__dfs(a[i].v),w[u]+=w[a[i].v];
    }
     
    int main(){
    	//freopen("yam.in","r",stdin);
    	//freopen("yam.out","w",stdout);
    	n=read<int>();m=read<int>();
    	for(int i=1;i<n;i++){
    		int u=read<int>();
    		int v=read<int>();
    		push(u,v);push(v,u);
    	}
    	dfs(1,0);
    	for(int i=1;i<=m;i++){
    		int u=read<int>();
    		int v=read<int>();
    		int Lca=lca(u,v);
    		w[Lca]-=2;
    		w[u]++;w[v]++;
    	}
    	__dfs(1);
    	for(int i=2;i<=n;i++){
    		if(w[i]==0)Ans+=m;
    		if(w[i]==1)Ans++;
    	}
    	printf("%lld
    ",Ans);
    }



  • 相关阅读:
    mouse_event模拟鼠标滚轮
    润乾报表配置技术路线
    建筑 物件 开心背单词 读句子,单词,字母,看图例, 翻译,看动画
    文字过渡动画,曲线过渡动画,,使用这个插件assign shape keys
    运动锻炼 开心背单词 读句子,单词,字母,看图例, 翻译,看动画,学英语,轻松背单词,简单背单词
    blender293 内置插件 精度绘画控件,PDT学习003,pdt tangents 切线
    日常用品 背单词 读句子 看图片 读单词 读字母 翻译, 看动画 学英语
    blender293 内置插件 精度绘画控件,PDT学习 precision drawing tools
    乔布斯 背单词 02 读句子 单词 字母 翻译,看动画 学英语 名言 我菜顾我在,我菜故我在,blender加python
    狐狸 和 乌鸦 英语 朗读句子 背单词
  • 原文地址:https://www.cnblogs.com/Cooook/p/7738510.html
Copyright © 2011-2022 走看看