AGC012B Splatter Painting

传送门

题意:
给你一个n个节点的简单无向图(无重边、自环),含有m条边。现在有q次操作。初始的时候所有点的颜色都为0。
每一次操作的描述如下:选择一个节点v[i],将与这个节点的距离小于等于d[i]的点全部都染成颜色c[i]。
现在要求你回答,完成这q次操作之后,每一个点的最终颜色是什么。

题解:
这道题d很小(≤10),可以暴力。但是直接暴力有可能会T(举个例子:菊花图)。
考虑将操作倒过来,那么就成了:将与这个节点的距离小于等于d[i]且还没有染色的点全部都染成颜色c[i]。
维护一个maxd[u]为u点操作到的最大的距离,那么当当前距离小于等于maxd[u]时,说明这次操作会被后面的操作抵消,可以忽略。
那么因为每个点最多只会被访问10次,所以时间复杂度为 O ( n d ) O(nd) O(nd)
注意这里不仅仅是起点要判断,访问到的点也要判断剩余距离和maxd的关系。

代码:

#include<cstdio>
#include<cstring>
#define INF 0x3f3f3f3f
#define maxn 100005
int n,m,q,s[maxn],d[maxn],x[maxn],maxd[maxn],c[maxn],que[maxn],fr,bk;
struct node { int v; node *nxt; } edge[maxn*2],*head[maxn],*ncnt;
void addedge(int u,int v)
{
	ncnt++;
	ncnt->v=v,ncnt->nxt=head[u];
	head[u]=ncnt;
}
void dfs(int u,int d,int x)
{
	if(maxd[u]>=d) return;
	if(!c[u]) c[u]=x;
	if(!d) return;
	maxd[u]=d;
	for(node *p=head[u];p;p=p->nxt) dfs(p->v,d-1,x);
}
int main()
{
	scanf("%d%d",&n,&m);
	ncnt=&edge[0];
	for(int i=1;i<=m;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		addedge(u,v); addedge(v,u);
	}
	memset(maxd,-1,sizeof(maxd));
	scanf("%d",&q);
	for(int i=1;i<=q;i++) scanf("%d%d%d",&s[i],&d[i],&x[i]);
	for(int i=q;i;i--) dfs(s[i],d[i],x[i]); 
	for(int i=1;i<=n;i++) printf("%d\n",c[i]);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值