https://codeforces.com/contest/757/problem/F
题解如标题所述,
tarjan支配树2500ms,TLE10
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define ll long long
#define ull unsigned long long
#define fi first
#define endl '\n'
#define se second
#define mp make_pair
#define pii pair<ll,ll>
#define all(x) x.begin(),x.end()
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
#define per(ii,a,b) for(int ii=b;ii>=a;--ii)
#define forn(i,x,g,e) for(int i=g[x];i;i=e[i].next)
#define forn(i,x,g,e) for(int i=g[x];i;i=e[i].next)
const int maxn=1e6+9,maxm=1e9+10,maxp=20;
const ll INF=1e18;
using namespace std;
int casn,n,m,k,root;
int cntin[maxn];
struct node{int to,next;};
struct graph{
node e[maxn];int head[maxn],nume;
void init(int n=maxn-5){nume=0;fill_n(head,n+1,0);}
void add(int a,int b){e[++nume]={b,head[a]};head[a]=nume;}
}inv,nxt,dom;
class domtree{public://@dom为最终的支配树,反向建边,root为根,cnt为每个点的支配点的数量@
int dfn[maxn],rev[maxn],anc[maxn];
int semi[maxn],idom[maxn];
int fa[maxn],mi[maxn],clo;
void init(int n=maxn-5){
clo=0;
rep(i,1,n)fa[i]=mi[i]=semi[i]=i,rev[i]=dfn[i]=anc[i]=idom[i]=0;
nxt.init(n),inv.init(n),dom.init(n);
}
void add(int a,int b){inv.add(b,a),nxt.add(a,b);}
int find(int now){
if(fa[now]==now) return now;
int fx=fa[now],y=find(fa[now]);
if(dfn[semi[mi[fx]]]<dfn[semi[mi[now]]])
mi[now]=mi[fx];
return fa[now]=y;
}
void tdfs(int now){
dfn[now]=++clo;rev[clo]=now;
forn(i,now,nxt.head,nxt.e)if(!dfn[nxt.e[i].to])
anc[nxt.e[i].to]=now,tdfs(nxt.e[i].to);
}
void maketree(int root,int n=maxn-5){
tdfs(root);
per(i,2,n){
int now=rev[i],tmp=n;
forn(i,now,inv.head,inv.e){
int to=inv.e[i].to;if(!dfn[to]) continue;
if(dfn[to]<dfn[now]) tmp=min(tmp,dfn[to]);
else find(to),tmp=min(tmp,dfn[semi[mi[to]]]);
}
semi[now]=rev[tmp];fa[now]=anc[now];
dom.add(semi[now],now);
now=rev[i-1];
forn(i,now,dom.head,dom.e){
int to=dom.e[i].to;find(to);
if(semi[mi[to]]==now) idom[to]=now;
else idom[to]=mi[to];
}
}
rep(i,2,n){
int to=rev[i];
if(idom[to]!=semi[to]) idom[to]=idom[idom[to]];
}
dom.init(n);
rep(i,1,n) if(i!=root)dom.add(idom[i],i);
}
int ans[maxn];
int cal(int now){
ans[now]=1;
forn(i,now,dom.head,dom.e) ans[now]+=cal(dom.e[i].to);
return ans[now];
}
}tree;
struct road{
int now;ll dis;
road(int a,ll b){now=a,dis=b;}
bool operator<(const road &rhs)const{return dis>rhs.dis;}
};
vector<road> g[maxn];
vector<ll> dis;
priority_queue<road>q;
void dijkstra(int st,int n=maxn-10){
dis.resize(n+2);fill(all(dis),INF);
q.emplace(st,0);dis[st]=0;
while(!q.empty()){
road t=q.top();q.pop();
for(auto e:g[t.now]){
ll cost=t.dis+e.dis;
if(cost<dis[e.now]){
dis[e.now]=cost;
q.emplace(e.now,cost);
}
}
}
}
int main() {IO;
cin>>n>>m>>root;
rep(i,1,m){
int a,b,c;
cin>>a>>b>>c;
g[a].emplace_back(b,c);
g[b].emplace_back(a,c);
}
dijkstra(root,n);
tree.init(n+1);
rep(i,1,n)for(auto e:g[i]){
int to=e.now;
if(dis[i]+e.dis==dis[to]) tree.add(i,to);
}
tree.maketree(root,n+1);
tree.cal(root);
int ans=0;
rep(i,1,n)if(i!=root)ans=max(ans,tree.ans[i]);
cout<<ans<<endl;
}
倍增灭绝树405 msAC
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define fi first
#define endl '\n'
#define se second
#define mp make_pair
#define pii pair<ll,ll>
#define all(x) x.begin(),x.end()
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
#define per(ii,a,b) for(int ii=b;ii>=a;--ii)
#define forn(i,x,g,e) for(int i=g[x];i;i=e[i].next)
#define forn(i,x,g,e) for(int i=g[x];i;i=e[i].next)
const int maxn=1e6+9,maxm=1e9+10,maxp=20;
const ll INF=1e18;
using namespace std;
int casn,n,m,k,root;
int cntin[maxn];
struct node{int to,next;};
class graph{public:
node e[maxn];int head[maxn],nume;
void init(int n=maxn-5){nume=0;fill_n(head,n+1,0);}
void add(int a,int b){e[++nume]={b,head[a]};head[a]=nume;}
}inv,nxt,dom;
class domtree{public://@DAG@
int deep[maxn],anc[maxn][maxp],que[maxn];
vector<int>edge;
void init(int n=maxn-5){
inv.init(n),nxt.init(n),dom.init(n);
edge.clear();
}
void bit(int &x,int h){
for(int i=0;h>0;++i){
if(h&1) x=anc[x][i];
h>>=1;
}
}
void add(int a,int b){nxt.add(a,b);inv.add(b,a);}
int lca(int a,int b){
if(deep[a]<deep[b]) swap(a,b);
bit(a,deep[a]-deep[b]);
if(a==b) return a;
per(i,0,maxp-1) if(anc[a][i]!=anc[b][i])
a=anc[a][i],b=anc[b][i];
return anc[a][0];
}
void tpsort(int n){
int tp=0,ed=0;
rep(i,1,n) {
if(!cntin[i]) {
que[ed++]=i;
inv.add(0,i);
nxt.add(i,0);
edge.push_back(i);
}
}
while(ed!=tp){
int now=que[tp++];
forn(i,now,inv.head,inv.e){
int to=inv.e[i].to;
cntin[to]--;
if(!cntin[to]) que[ed++]=to,edge.push_back(to);
}
}
}
void maketree(int n){
tpsort(n);
for(auto i:edge){
int fa=-1;
forn(j,i,nxt.head,nxt.e){
int to=nxt.e[j].to;
if(fa==-1) fa=to;
else fa=lca(fa,to);
}fa=fa==-1?0:fa;
deep[i]=deep[fa]+1,anc[i][0]=fa;
rep(j,1,maxp-1) anc[i][j]=anc[anc[i][j-1]][j-1];
dom.add(fa,i);
}
}
int ans[maxn];
int cal(int now){
ans[now]=1;
forn(i,now,dom.head,dom.e) ans[now]+=cal(dom.e[i].to);
return ans[now];
}
}tree;
struct road{
int now;ll dis;
road(int a,ll b){now=a,dis=b;}
bool operator<(const road &rhs)const{return dis>rhs.dis;}
};
vector<road> g[maxn];
vector<ll> dis;
priority_queue<road>q;
void dijkstra(int st,int n=maxn-10){
dis.resize(n+2);fill(all(dis),INF);
q.emplace(st,0);dis[st]=0;
while(!q.empty()){
road t=q.top();q.pop();
for(auto e:g[t.now]){
ll cost=t.dis+e.dis;
if(cost<dis[e.now]){
dis[e.now]=cost;
q.emplace(e.now,cost);
}
}
}
}
int main() {IO;
cin>>n>>m>>root;
rep(i,1,m){
int a,b,c;
cin>>a>>b>>c;
g[a].emplace_back(b,c);
g[b].emplace_back(a,c);
}
dijkstra(root,n);
tree.init(n+1);
rep(i,1,n)for(auto e:g[i]){
int to=e.now;
if(dis[i]+e.dis==dis[to]) {
tree.add(to,i);
++cntin[to];
}
}
tree.maketree(n+1);
tree.cal(root);
int ans=0;
rep(i,1,n)if(i!=root)ans=max(ans,tree.ans[i]);
cout<<ans<<endl;
}