codeforces1472G. Moving to the Capital

二分抄程式碼發表於2021-01-05

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

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

我們按照離1的距離從大到小列舉點u然後列舉他的出邊v,如果d[u]<d[v]說明u可以走到v,之後再用一次2,且v已經被處理過了,如果d[u]>=d[v]說明走這條邊就要用到1次2了,那麼之後就只能用1,那麼d[v]就是u走u->v能得到的最小值了

#include<bits/stdc++.h>
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<int> 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<int> 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;
}

 

相關文章