记录编号 222975 评测结果 AAAAAAAAAA
题目名称 卡赞群岛 最终得分 100
用户昵称 GravatarSatoshi 是否通过 通过
代码语言 C++ 运行时间 0.406 s
提交时间 2016-02-06 00:23:22 内存使用 4.17 MiB
显示代码纯文本
#include <fstream>
#include <algorithm>
#include <vector>
#define N 20010
#define M 200010
using namespace std;
ifstream in("kezan.in");
ofstream out("kezan.out");
int n,m;
vector<int> G[N],C[N],F[N],B[N];
bool l[N]={0},vis[N]={0};
int dfn[N]={0},low[N]={0};
int tim=0;
int s[N]={0},top=0;
int color[N]={0};
int col=0;
int f[N]={0},st[N]={0},en[N]={0},INF;
int start,end;
int q[N]={0};
class edge
{
public:
	int u,v,w;
	void make(int a,int b,int c)
	{
		u=a;
		v=b;
		w=c;
	}
	void print()
	{
		out<<u<<' '<<v<<' '<<w<<endl;
	}
}e[M];
void add1(int u,int v,int w)
{
	G[u].push_back(v);
	G[v].push_back(u);
	C[u].push_back(w);
	C[v].push_back(w);
}
void add2(int u,int v,int w)
{
	F[u].push_back(v);
	F[v].push_back(u);
	B[u].push_back(w);
	B[v].push_back(w);
}
void tarjan(int u,int fa)//求双联通分量
{
	int i,v,w;
	dfn[u]=low[u]=++tim;
	s[++top]=u;
	l[u]=1;
	for(i=0;i<G[u].size();i++)
	{
		v=G[u][i];
		if(v!=fa)
		if(!dfn[v])
		{
			tarjan(v,u);
			low[u]=min(low[u],low[v]);
		}
		else if(l[v])low[u]=min(low[u],dfn[v]);
	}
	if(dfn[u]==low[u])
	{
		col++;
		do
		{
			v=s[top];
			l[v]=0;
			color[v]=col;
			top--;
		}while(u!=v);
	}
}
void BFS(int s)//求直径的两个端点,则最长链为max(s[i],t[i])
{
	int i,u,v,w,l,r;
	l=r=1;
	for(i=1;i<=n;i++)
	{
		vis[i]=0;
		f[i]=INF;
	}
	q[++r]=s;
	f[s]=0;
	while(l<=r)
	{
		u=q[l];
		l++;
		vis[u]=1;
		for(i=0;i<F[u].size();i++)
		{
			v=F[u][i];
			w=B[u][i];
			if(!vis[v])
			{
				f[v]=f[u]+w;
				q[++r]=v;
			}
		}
	}
}
void read()
{
	int i,u,v,w;
	in>>n>>m;
	for(i=1;i<=m;i++)
	{
		in>>u>>v>>w;
		e[i].make(u,v,w);
		add1(u,v,w);
	}
	for(i=1;i<=n;i++)
	{
		if(!dfn[i])tarjan(i,0);
	}
}
void work()
{
	int i,u,v,ans;
	int temp=0;
	for(i=1;i<=m;i++)
	{
		u=e[i].u;
		v=e[i].v;
		if(color[u]!=color[v])//不同的商业联盟建边
		{
			add2(color[u],color[v],e[i].w);
		}
	}
	BFS(1);//从1号开始,最长的f[]为直径的一个端点
	for(i=1;i<=n;i++)
	{
		if(f[i]>temp)
		{
			temp=f[i];
			start=i;
		}
	}
	BFS(start);//从直径的一个端点开始,最长的f[]为直径的另一个端点
	temp=0;
	for(i=1;i<=n;i++)
	{
		if(f[i]>temp)
		{
			temp=f[i];
			end=i;
		}
		st[i]=f[i];
	}
	BFS(end);
	for(i=1;i<=n;i++)en[i]=f[i];
	for(i=1;i<=n;i++)
	{
		ans=max(st[color[i]],en[color[i]]);//最长链一定为该点到直径两端点的最大值
		out<<ans<<endl;
	}
}
int main()
{
	read();
	work();
	return 0;
}