Codeforces 757F: Team Rocket Rises Again(支配树)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35649707/article/details/64132831

Description

      2017新年到!Bash小朋友想给他的好友们送礼物。在他的国家里,有 n 座城市和 m 条双向道路(这里保证这 n 座城市是联通的)。Bash住在城市 s 中。对于每个城市(包括Bash居住的城市 s ),Bash都有且仅有一个好友。为了给好友们一个惊喜,他决定送一只皮卡丘给他们。他当然想让皮卡丘尽可能快地到达好友们手中。

      于是,他给皮卡丘们设定了路线:从 s 出发到各自目的地的最短路径。由于Bash是个完美主义者,他通知了他的所有好友皮卡丘的预计到达时间(即走最短路径的耗时)。一只皮卡丘每秒走1个单位长度。他的好友们都很高兴且默默地期待皮卡丘到达的时刻。但是,如果一位好友的皮卡丘在预计到达时间没有到达(包括晚点或者永远不能到达这两种情况),那么那位好友会很不开心。

      不幸的是,Team Rocket想来搞破坏。他将在Bash小朋友正准备发送皮卡丘的时刻摧毁一座城市。如果一座城市被摧毁了,那么所有连向这座城市的路也同时被摧毁,则皮卡丘们可能要绕行更远的路。

      现在,对于每一个城市 i ,Team Rocket想知道如果摧毁了城市 i ,会使得多少位好友不开心。

      特别地,如果摧毁的城市恰好为 s ,则所有好友都收不到礼物, n 位好友都会不开心。

Input

      第一行包含三个整数 n,m,s(2n105,1mmin(n(n1)2,3×105),1sn) ,分别表示城市的数量、道路的数量、Bash住的城市。

      接下来 m 行,每行三个整数 u,v,w(1u,vn,uv,1w109) ,表示城市 u 和城市 v 之间有一条长度为 w 个单位的路。

      数据保证没有重边没有自环。

Output

      输出 n 行,第 i 行表示摧毁第 i 个城市会让多少个好友不开心。

Sample Input

【样例输入1】
4 4 3
1 2 1
2 3 1
2 4 1
3 1 1
【样例输入2】
7 11 2
1 2 5
1 3 5
2 4 2
2 5 2
3 6 3
3 7 3
4 6 2
3 4 2
6 7 3
4 5 7
4 7 7

Sample Output

【样例输出1】
1
2
4
1
【样例输出2】
1
7
1
4
1
1
1

HINT

【样例解释】

摧毁城市1,只有城市1的朋友不开心。

摧毁城市2,城市2和城市4的朋友都不开心。

摧毁城市3,所有城市的朋友都不开心。

摧毁城市4,城市4的朋友不开心。

【数据范围与约定】

      子任务1(30分): n1000,m3000

      子任务2(70分): n100000,m300000




建出最短路图后上支配树即可。

注意这是一个DAG,可以用拓扑图上的简单方法构造支配树。这里贴一份处理带环的支配树。

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline int rd(){
char ch=getchar();int i=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}
return i*f;
}
const int N=2e5+50,M=3e5+50;
const ll INF=0x3f3f3f3f3f3f3f3f;
int n,m,s,ans;
struct Graph{
int g[N],v[M*2],nt[M*2],fa[N],sze[N],vis[N],ec;
int dfn[N],id[N],sdom[N],idom[N],mnsd[N],anc[N],tot;
ll dis[N*2];
vector<int>buc[N];
vector<int>pre[N];
vector< pair<int,int> >edge[N];
inline void add(int x,int y){
nt[++ec]=g[x];g[x]=ec;v[ec]=y;
pre[y].push_back(x);
}
inline void getanc(int p){
if(anc[p]!=p)getanc(anc[p]);
if(dfn[sdom[mnsd[anc[p]]]]<dfn[sdom[mnsd[p]]])mnsd[p]=mnsd[anc[p]];
anc[p]=anc[anc[p]];
}
inline int eval(int p){
getanc(p);
return mnsd[p];
}
inline void dij(int src){
memset(dis,0x3f,sizeof(dis));
priority_queue< pair<ll,int> >q;
dis[src]=0;q.push( make_pair(0,src) );
while(!q.empty()){
int u=q.top().second;q.pop();
if(vis[u])continue;
vis[u]=1;
for(int j=edge[u].size()-1;j>=0;j--){
int v=edge[u][j].first,c=edge[u][j].second;
if(dis[v]<=dis[u]+c)continue;
dis[v]=dis[u]+c;q.push( make_pair(-dis[v],v) );
}
}
for(int i=1;i<=n;i++){
for(int j=edge[i].size()-1;j>=0;j--){
int v=edge[i][j].first,c=edge[i][j].second;
if(dis[v]==dis[i]+c)add(i,v);
}
}
}
inline void dfs(int now,int f){
dfn[now]=++tot;id[tot]=now;fa[now]=f;
sdom[now]=(mnsd[now]=(anc[now]=now));
for(int j=g[now];j;j=nt[j]){
if(!dfn[v[j]])dfs(v[j],now);
}
}
inline void build(){
for(int i=tot;i>=2;i--){
int u=id[i];
for(int j=pre[u].size()-1;j>=0;j--){
int v=eval(pre[u][j]);
if(dfn[sdom[u]]>dfn[sdom[v]])sdom[u]=sdom[v];
}
int f=fa[u];
anc[u]=f;
buc[sdom[u]].push_back(u);
for(int j=buc[f].size()-1;j>=0;j--){
int v=buc[f][j],t=eval(v);
if(dfn[sdom[t]]<dfn[sdom[v]])idom[v]=t;
else idom[v]=sdom[v];
}
buc[f].clear();
}
for(int i=2;i<=tot;i++){
int u=id[i];
if(idom[u]!=sdom[u])idom[u]=idom[idom[u]];
}
for(int i=tot;i>=2;i--){
int u=id[i];sze[u]++;
sze[idom[u]]+=sze[u];
ans=max(ans,sze[u]);
}
}
}g;
int main(){
n=rd(),m=rd(),s=rd();
for(int i=1;i<=m;i++){
int x=rd(),y=rd(),c=rd();
g.edge[x].push_back(make_pair(y,c));
g.edge[y].push_back(make_pair(x,c));
}
g.dij(s);
g.dfs(s,0);
g.build();
cout<<ans<<endl;
}


阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页