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(2≤n≤105,1≤m≤min(n(n−1)2,3×105),1≤s≤n) ,分别表示城市的数量、道路的数量、Bash住的城市。
接下来 m 行,每行三个整数 u,v,w(1≤u,v≤n,u≠v,1≤w≤109) ,表示城市 u 和城市 v 之间有一条长度为 w 个单位的路。
数据保证没有重边没有自环。
Output
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分): n≤1000,m≤3000
子任务2(70分): n≤100000,m≤300000
建出最短路图后上支配树即可。
注意这是一个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;}