codeforces1472G. Moving to the Capital

https://codeforces.com/contest/1472/problem/G

一开始ans[i]=d[i]

我们按照离1的距离从大到小枚举点u然后枚举他的出边v,如果d[u]=d[v]说明走这条边就要用到1次2了,那么之后就只能用1,那么d[v]就是u走u->v能得到的最小值了

#include
using namespace std;
typedef long long ll;

const int maxl=3e5+10;

int n,m,k,cnt,tot,cas;
int a[maxl],ans[maxl],d[maxl];
bool vis[maxl];
char s[maxl];
vector e[maxl],b[maxl];

inline void prework()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		e[i].clear(),b[i].clear();
	for(int i=1;i<=m;i++)
	{
		int u,v;scanf("%d%d",&u,&v);
		e[u].push_back(v);
	}
	for(int i=1;i<=n;i++)
		vis[i]=false;
	queue q;
	q.push(1);d[1]=0;vis[1]=true;
	while(!q.empty())
	{
		int u=q.front();q.pop();b[d[u]].push_back(u);
		for(int v:e[u])
		if(!vis[v])
		{
			d[v]=d[u]+1;
			q.push(v);vis[v]=true;
		}
	}
}

inline void mainwork()
{
	for(int i=1;i<=n;i++)
		ans[i]=d[i];
	for(int i=n;i>=0;i--)
		for(int u:b[i])
			for(int v:e[u])
			if(d[v]>d[u])
				ans[u]=min(ans[u],ans[v]);	
			else
				ans[u]=min(ans[u],d[v]);
}

inline void print()
{
	for(int i=1;i<=n;i++)
		printf("%d%c",ans[i]," \n"[i==n]);
}

int main()
{
	int t=1;
	scanf("%d",&t);
	for(cas=1;cas<=t;cas++)
	{
		prework();
		mainwork();
		print();
	}
	return 0;
}

 

你可能感兴趣的:(codeforces1472G. Moving to the Capital)