2018.10.04 NOIP模擬 航班(tarjan+樹形)
阿新 • • 發佈:2018-12-13
描述
L因為業務繁忙,經常會到處出差。因為他是航空公司的優質客戶,於是某個航空公司給了他一個優惠券。 他可以利用這個優惠券在任何一個國家內的任意城市間免費旅行,當他的路線跨國才會產生費用。L有一個航空公司的價格表與航線。而且每個城市出發都能到所有的城市,2個城市間可能有不止一個航班,一個國家內的2個城市間一定有不同的路線,但是不同國家的城市間只有一條路線。L想知道從每個城市出發到產生費用最多的城市,不過你不能重複在一個航班上飛來飛去產生費用,必須沿最少的費用路線飛行
輸入
第一行,兩個整數 N,M,表示N 個城市, M 條航線。 接下來 M 行,每行三個整數 a,b,c,表示城市 a,b 之間有一條費用為 c 的航線。
輸出
共 N 行,第 i 行為從城市 i 出發到達每個城市額外費用的最大值。
樣例輸入
6 6 1 4 2 1 2 6 2 5 3 2 3 7 6 3 4 3 1 8
樣例輸出
4 4 4 6 7 7
提示
【解釋】 有四個國家,包含的城市分別為 {1,2,3},{4},{5},{6}。 從城市 1 出發到達城市 6,乘坐(1,3)(3,6)兩個航班費用最大,(1,3)在國內為免費航班, (3,6)的費用為 4,所以從 1 出發的最大費用為 4。 【資料規模】 對於 40%的資料 1<=N<=1000,1<=M<=1000 對於 100%的資料 1<=N<=20000,1<=M<=200000
考場上自己yy了一個雙連通只有40分。 然後換根dp求最長路就行了。 程式碼:
#include<bits/stdc++.h>
#define ll long long
#define N 20005
#define M 2000005
using namespace std;
int first[N],First[N],Cnt=0,n,m,cnt=-1,tot=0,dfn[N],low[N],stk[N],col[N],top=0,blo=0;
ll f[N],ans[N],h[N];
set<ll>S[N];
struct edge{int v,next;ll w;}e[M<< 1],g[M<<1];
struct Edge{int u,v;ll w;}tt[M];
inline void add(int u,int v,ll w){e[++cnt].v=v,e[cnt].next=first[u],first[u]=cnt;}
inline void Add(int u,int v,ll w){g[++Cnt].v=v,g[Cnt].w=w,g[Cnt].next=First[u],First[u]=Cnt;}
inline ll read(){
ll ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
inline void tarjan(int p,int pre){
dfn[p]=low[p]=++tot,stk[++top]=p;
for(int i=first[p];~i;i=e[i].next){
int v=e[i].v;
if(i==(pre^1))continue;
if(!dfn[v])tarjan(v,i),low[p]=min(low[p],low[v]);
else low[p]=min(low[p],dfn[v]);
}
if(low[p]==dfn[p]){
++blo;
int x;
do col[x=stk[top--]]=blo;while(x!=p);
}
}
inline void dfs1(int p,int fa){
f[p]=0;
for(int i=First[p];i;i=g[i].next){
int v=g[i].v;
if(v==fa)continue;
dfs1(v,p),f[p]=max(f[p],f[v]+g[i].w);
}
}
inline void dfs2(int p,int fa){
ans[p]=max(f[p],ans[p]);
for(int i=First[p];i;i=g[i].next){
int v=g[i].v;
if(v==fa)continue;
S[p].insert(f[v]+g[i].w);
}
set<ll>::iterator its=S[fa].end();
for(int i=First[p];i;i=g[i].next){
int v=g[i].v;
if(v==fa)continue;
S[p].erase(f[v]+g[i].w);
set<ll>::iterator it=S[p].end();
if(S[p].size())--it,ans[v]=g[i].w+*it,S[v].insert(g[i].w+*it);
else ans[v]=g[i].w;
dfs2(v,p),S[p].insert(f[v]+g[i].w);
}
}
int main(){ freopen("prize.in","r",stdin);
freopen("prize.out","w",stdout);
memset(first,-1,sizeof(first));
n=read(),m=read();
for(int i=1;i<=m;++i){
int u=read(),v=read();
ll w=read();
tt[i].u=u,tt[i].v=v,tt[i].w=w;
add(u,v,w),add(v,u,w);
}
tarjan(1,cnt+10);
for(int i=1;i<=m;++i){
int u=tt[i].u,v=tt[i].v;
ll w=tt[i].w;
if(col[u]==col[v])continue;
Add(col[u],col[v],w),Add(col[v],col[u],w);
}
dfs1(1,0),S[1].insert(0),dfs2(1,0);
for(int i=1;i<=n;++i)printf("%d\n",ans[col[i]]);
return 0;
}