codeforces 757F 求最短路后建立DAG后跑灭绝树
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; }