AtCoder Beginner Contest 138 D - Ki(树上差分)

题目链接————

题意大致是给你一棵树,然后每个节点都有一个计算器,有m个操作,每次在x节点处增加val的值,x相应的子树上的节点计算器都会增加val的值。

思路:

昨天晚上没想出好的做法,然后进行了m次dfs,当然理所当然的TLE。今天看discuss有人说先用数组记录,再用一次dfs进行前缀统计,我有点恍然大悟,然后就试了下,结果Wa了三组数据,我对一次dfs的做法有些质疑,如果两个点有公共子节点的话那怎么办呢?我想我蠢了,前提已经说了,这是棵树。。

若无向连通图G中有n个结点,n-1条边,则G为树  这是树的等价定义之一

后来看到有人给的数据,发现数据是随机给的。。。不是按照树的结构来的。

然后需要把节点之间设置为无向边,vis标记节点,dfs 或者bfs都可以。

BFS Code:

#include
using namespace std;
typedef long long LL;
const LL N = 200010;
struct Edge
{
    LL next;
    LL dis;
    LL to;
}edge[N*2];
LL head[N*2];
LL res[N*2];
LL r[N*2];
LL tot;
LL n,m;
bool vis[N*2];
inline void add(LL from,LL to)
{
    edge[++tot].next = head[from];
    edge[tot].to = to;
    head[from] = tot;
}
void init()
{
    memset(head,-1,sizeof(head));
}
void bfs()
{
   queue Q;
   Q.push(1);
   while(Q.size())
   {
       LL x = Q.front();
       vis[x] = 1;
       Q.pop();
       for(LL i = head[x];~i;i = edge[i].next)
       {
           LL y = edge[i].to;
         if(!vis[y]) {
           res[y] += res[x];
           Q.push(y);
       }
       }
   }

}
int main()
{
  //freopen("input.txt","r",stdin);
   init();
   scanf("%lld%lld",&n,&m);
   LL f,t;
   for(LL i = 1;i<=n-1;++i)
   {
       scanf("%lld%lld",&f,&t);
       add(f,t);
       add(t,f);
   }
   for(LL i = 1;i<=m;++i)
   {
       scanf("%lld%lld",&f,&t);
       res[f] += t;
   }
   bfs();
   for(LL i = 1;i<=n;++i)
    printf("%lld ",res[i]);
}

DFS Code:

#include
using namespace std;
typedef long long LL;
const int N = 200010;
struct Edge
{
    int next;
    int dis;
    int to;
}edge[N*2];
int head[N*2];
int res[N*2];
int r[N*2];
int tot;
int n,m;
bool vis[N*2];
inline void add(int from,int to)
{
    edge[++tot].next = head[from];
    edge[tot].to = to;
    head[from] = tot;
}
void init()
{
    memset(head,-1,sizeof(head));
}
void dfs(int id)
{
    vis[id] = 1;
    for(int i = head[id];~i;i = edge[i].next)
    {
        int y = edge[i].to;
        if(!vis[y]) res[y] += res[id],dfs(y);
    }
}
int main()
{
  //freopen("input.txt","r",stdin);
   init();
   scanf("%d%d",&n,&m);
   int f,t;
   for(int i = 1;i<=n-1;++i)
   {
       scanf("%d%d",&f,&t);
       add(f,t);
       add(t,f);
   }
   for(int i = 1;i<=m;++i)
   {
       scanf("%d%d",&f,&t);
       res[f] += t;
   }
   dfs(1);
   for(int i = 1;i<=n;++i)
    printf("%d ",res[i]);
}
#include
using namespace std;
#define read(x) scanf("%d",&x)
#define write(x) printf("%d ",x)
const int N = 2e5;
int head[N+5],tot;
int d[N+5];
struct Edge
{
    int next;
    int to;
}edge[N*2+5];
inline void add(int from,int to)
{
    edge[++tot].next = head[from];
    edge[tot].to= to;
    head[from] = tot;
}
void dfs(int x,int fa){
    d[x] += d[fa];
    for(int i = head[x];~i;i = edge[i].next)
    {
        int y = edge[i].to;
        if(y!=fa) dfs(y,x);
    }
}
int main()
{
    memset(head,-1,sizeof(head));
    int n,m;
    read(n);read(m);
    int f,t;
    for(int i = 1;i<=n - 1;++i){
        read(f);
        read(t);
        add(f,t);
        add(t,f);
    }
    for(int i = 1;i<=m;++i){
      read(f);
      read(t);
      d[f] += t;
    }
    dfs(1,0);
    for(int i = 1;i<=n;++i)    write(d[i]);
}

 

你可能感兴趣的:(—,—,—,—,图论—,—,—,—,树上差分)