Atcoder #2362 Splatter Painting(dfs+优化)

原题链接(vjudge上的)
这道题的大意是:对于一个无向图,有n个节点和m条边,每个操作将与节点v的距离小于等于d的节点涂为颜色c。 n,m,p<=105 d<=10
给出输入输出样例:
Atcoder #2362 Splatter Painting(dfs+优化)_第1张图片
Atcoder #2362 Splatter Painting(dfs+优化)_第2张图片
要解决这道题:我们只需要注意两个点:
1.离线处理操作,将操作倒序进行处理,这样就可以避免一个点被重复染色
2.基于第1点,在dfs时记录该点在被涂色是距离涂色中心点v的距离r,当这个点再次被搜到时,只需判断当前的r是否大于之前记录的r,否则return。
时间复杂度能控制为O(10n) (每个点最多被搜10次)
附上代码:

#include
#include
#include
#define maxn 200050
#define add(u,v) (to[++top]=head[u],head[u]=top,w[top]=v)
#define For(x) for(int h=head[x],o=w[h];h;o=w[h=to[h]])
using namespace std;
int n,m,to[maxn],head[maxn],w[maxn],u,v,top;
int a[maxn],b[maxn],c[maxn],co[maxn],r[maxn],q,i;
void dfs(int x,int rg,int col)
{
    if (rg<=r[x]||rg<=0) return;
    r[x]=rg; 
    if (co[x]==0) co[x]=col;
    For(x) dfs(o,rg-1,col);
}
int main()
{
    scanf("%d%d",&n,&m);
    while (m--)
    {
        scanf("%d%d",&u,&v);
        add(u,v); add(v,u);
    }
    scanf("%d",&q);
    for (i=1;i<=q;i++) scanf("%d%d%d",&a[i],&b[i],&c[i]);
    memset(co,0,sizeof(co)); memset(r,0,sizeof(r));
    for (i=q;i>=1;i--) dfs(a[i],b[i]+1,c[i]);
    for (i=1;i<=n;i++) printf("%d\n",co[i]);
    return 0;
}

你可能感兴趣的:(dfs,dfs,优化)