zoukankan      html  css  js  c++  java
  • 【POJ3417】Network-LCA算法+树上差分

    题目大意:一棵有N个点的树,再往里面加入M条新边,现在要破坏其中的两条边,要求一条是原来树中的边,一条是新边,求方案的数量。

    做法:点击打开链接

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int n,m,tot,first[100010],firstq[100010],f[100010],fa[100010],dp[100010],lca[100010];
    long long ans=0;
    bool vis[100010];
    struct {int v,next;} e[200010],q[200010];
    
    void insert(int a,int b)
    {
      e[++tot].v=b;
      e[tot].next=first[a];
      first[a]=tot;
    }
    
    void insertq(int a,int b)
    {
      q[++tot].v=b;
      q[tot].next=firstq[a];
      firstq[a]=tot;
    }
    
    int find(int x)
    {
      int r=x,i=x,j;
      while(f[r]!=r) r=f[r];
      while(i!=r) {j=f[i];f[i]=r;i=j;}
      return r;
    }
    
    void merge(int a,int b)
    {
      f[find(a)]=find(b);
    }
    
    void tarjan(int v)
    {
      f[v]=v;
      for(int i=first[v];i;i=e[i].next)
        if (e[i].v!=fa[v])
    	{
    	  fa[e[i].v]=v;
    	  tarjan(e[i].v);
    	}
      vis[v]=1;
      for(int i=firstq[v];i;i=q[i].next)
        if (vis[q[i].v]) lca[(i+1)/2]=find(q[i].v);
      merge(v,fa[v]);
    }
    
    void DP(int v)
    {
      for(int i=first[v];i;i=e[i].next)
        if (e[i].v!=fa[v])
    	{
    	  DP(e[i].v);
    	  dp[v]+=dp[e[i].v];
    	}
      if (v!=1)
      {
        if (dp[v]==0) ans+=m;
        if (dp[v]==1) ans++;
      }
    }
    
    int main()
    {
      scanf("%d%d",&n,&m);
      memset(first,0,sizeof(first));
      memset(firstq,0,sizeof(firstq));
      memset(vis,0,sizeof(vis));
      memset(dp,0,sizeof(dp));
      fa[1]=tot=0;
      for(int i=1;i<n;i++)
      {
        int a,b;
    	scanf("%d%d",&a,&b);
    	insert(a,b);insert(b,a);
      }
      tot=0;
      for(int i=1;i<=m;i++)
      {
        int a,b;
    	scanf("%d%d",&a,&b);
    	insertq(a,b);insertq(b,a);
      }
      tarjan(1);
      for(int i=1;i<=m;i++)
      {
        int a=q[i*2].v,b=q[i*2-1].v;
        dp[a]++;dp[b]++;dp[lca[i]]-=2;
      }
      DP(1);
      printf("%lld
    ",ans);
      
      return 0;
    }
    


  • 相关阅读:
    springboot文件上传: 单个文件上传 和 多个文件上传
    Eclipse:很不错的插件-devStyle,将你的eclipse变成idea风格
    springboot项目搭建:结构和入门程序
    POJ 3169 Layout 差分约束系统
    POJ 3723 Conscription 最小生成树
    POJ 3255 Roadblocks 次短路
    UVA 11367 Full Tank? 最短路
    UVA 10269 Adventure of Super Mario 最短路
    UVA 10603 Fill 最短路
    POJ 2431 Expedition 优先队列
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793951.html
Copyright © 2011-2022 走看看