版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/86521277
传送门
解析:
题意:给出一个有向图,求删除一个节点后,最多可能有多少个从 开始的最短路边长(删除的节点距离变为INF)(不可以删除S)
思路:
支配树裸题。
显然删除的点要在 到其他点的最短路上,而且是必经点。
跑一个最短路,构建出以 为根的最短路DAG,然后Lengauer-Tarjan一波求出支配树。选择 最大的儿子,就完了。。。
当然DAG有常数较小的做法,不过在允许边权为 的情况最短路DAG就不存在了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define pc put_char
#define cs const
namespace IO{
namespace IOONLY{
cs int Rlen=1<<20|1;
char buf[Rlen],*p1,*p2;
}
inline char get_char(){
using namespace IOONLY;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
}
using namespace IO;
cs int N=200005;
int n,m;
vector<int> edge[N];
vector<int> w[N];
inline void addedge(int u,int v,int val){
edge[u].push_back(v);
edge[v].push_back(u);
w[u].push_back(val);
w[v].push_back(val);
}
ll dist[N];
set<pair<ll,int> > q;
int S;
inline void Dij(){
memset(dist,0x3f,sizeof dist);
dist[S]=0;
q.insert(make_pair(0ll,S));
while(!q.empty()){
int u=q.begin()->second;
q.erase(q.begin());
for(int re e=0,v;e<edge[u].size();++e){
v=edge[u][e];
if(dist[v]>dist[u]+w[u][e]){
q.erase(make_pair(dist[v],v));
dist[v]=dist[u]+w[u][e];
q.insert(make_pair(dist[v],v));
}
}
}
}
vector<int> g[N],revg[N],dt[N];
inline void build(){
Dij();
for(int re u=1;u<=n;++u){
for(int re e=0,v;e<edge[u].size();++e){
v=edge[u][e];
if(dist[v]==dist[u]+w[u][e]){
g[u].push_back(v);
revg[v].push_back(u);
}
}
}
}
stack<int,vector<int> > dom[N];
int fa[N],dfn[N],id[N],dfs_clock;
void dfs(int u){
id[dfn[u]=++dfs_clock]=u;
for(int re e=0,v;e<g[u].size();++e){
v=g[u][e];
if(dfn[v])continue;
fa[v]=u;dfs(v);
}
}
int bel[N],semi[N],idom[N],nd[N];
inline int getfa(int x){
if(bel[x]==x)return x;
int tmp=getfa(bel[x]);
if(dfn[semi[nd[bel[x]]]]<dfn[semi[nd[x]]])nd[x]=nd[bel[x]];
return bel[x]=tmp;
}
inline void tarjan(){
for(int re i=dfs_clock,u;i>1;--i){
u=id[i];
for(int re e=0,v;e<revg[u].size();++e){
v=revg[u][e];
if(!dfn[v])continue;
getfa(v);
if(dfn[semi[nd[v]]]<dfn[semi[u]])semi[u]=semi[nd[v]];
}
dom[semi[u]].push(u);
u=bel[u]=fa[u];
while(dom[u].size()){
int v=dom[u].top();dom[u].pop();
getfa(v);
if(semi[nd[v]]==u)idom[v]=u;
else idom[v]=nd[v];
}
}
for(int re i=2,u;i<=dfs_clock;++i){
u=id[i];
if(semi[u]^idom[u])idom[u]=idom[idom[u]];
dt[idom[u]].push_back(u);
}
}
int siz[N];
void dfs_dt(int u){
siz[u]=1;
for(int re e=0,v;e<dt[u].size();++e){
v=dt[u][e];
dfs_dt(v);
siz[u]+=siz[v];
}
}
signed main(){
n=getint(),m=getint(),S=getint();
for(int re i=1;i<=m;++i){
int u=getint(),v=getint(),val=getint();
addedge(u,v,val);
}
for(int re i=1;i<=n;++i)semi[i]=nd[i]=bel[i]=i;
build();
dfs(S);
tarjan();
dfs_dt(S);
int ans=0;
for(int re e=0;e<dt[S].size();++e){
ans=max(ans,siz[dt[S][e]]);
}
cout<<ans<<endl;
return 0;
}