1. 程式人生 > >2018.10.04 NOIP模擬 航班(tarjan+樹形)

2018.10.04 NOIP模擬 航班(tarjan+樹形)

描述

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; }