題目鏈接 LOJ
洛谷P4630
先對這張圖建圓方樹。
對于S->T這條(些)路徑,其對答案的貢獻為可能經過的所有點數,那么我們把方點權值設為聯通分量的大小,可以直接去求樹上路徑權值和。
因為兩方點之間的圓點會計算兩次,所以圓點權值設為-1就好了。
那么現在有 \(n^2\) 個點對,求每個點對之間的路徑上點的權值和。
對每個點計算一下被計算次數就可以了。這個路徑次數計算注意考慮全。。
另外點對是圓點間的,所以方點初始sz[]為0,圓點的sz[]才是1。
方點其實建一條邊就可以。
LOJ為什么找不到代碼框的位置了。。交了兩次文件CE了兩次,是代碼不能加注釋?
好了 原來網頁放大后代碼框就沒了。。
//344ms 11.82MB/2573ms 12668K
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
const int N=100005<<1,M=4e5+7;//2N!→_→int n,m,tot,sk[N],top,dfn[N],low[N],Index,fa[N],sz[N],val[N];
long long Ans;
struct Graph
{int H[N],Enum,to[M],nxt[M];inline void Add_E(int u,int v){to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;}inline void AddEdge(int u,int v){Add_E(u,v), Add_E(v,u);}
}G,T;inline int read()
{int now=0;register char c=gc();for(;!isdigit(c);c=gc());for(;isdigit(c);now=now*10+c-'0',c=gc());return now;
}
void Tarjan(int x)
{dfn[x]=low[x]=++Index, sk[++top]=x, val[x]=-1;for(int v,i=G.H[x]; i; i=G.nxt[i])if(!dfn[v=G.to[i]]){fa[v]=x, Tarjan(v), low[x]=std::min(low[x],low[v]);if(dfn[x]<=low[v]){T.Add_E(x,++tot), val[tot]=1;do{T.Add_E(tot,sk[top--]), ++val[tot];}while(sk[top+1]!=v);//別在這把x彈掉。。x可能是多個環的根節點。}}else low[x]=std::min(low[x],dfn[v]);
}
void pre_DFS(int x,int f)//這個dfs還是可以省的吧...
{if(x<=n) sz[x]=1;for(int i=T.H[x]; i; i=T.nxt[i])if(T.to[i]!=f) pre_DFS(T.to[i],x), sz[x]+=sz[T.to[i]];
}
void Solve(int x,int f,int tot)
{if(x<=n) Ans+=1ll*(tot-1)*val[x];//以x為起點的路徑數 Ans+=1ll*(tot-sz[x])*sz[x]*val[x];//起點在x到根方向的一側,終點在另一側 for(int i=T.H[x]; i; i=T.nxt[i])Ans+=1ll*val[x]*(tot-sz[T.to[i]])*sz[T.to[i]], Solve(T.to[i],x,tot);//起點在子樹方向,終點到其它地方去(包括x)//注意剛開始算了個以x為起點的數,直接交換起點終點(*2)是不對的!
}
//void Solve(int x,int f,int tot)
//{
// if(x<=n) Ans+=2ll*(tot-1)*val[x];//以x為起點&終點的路徑數
// int sum=tot-sz[x];
// for(int i=T.H[x]; i; i=T.nxt[i])
// Ans+=2ll*val[x]*sum*sz[T.to[i]], sum+=sz[T.to[i]], Solve(T.to[i],x,tot);
//}int main()
{tot=/*!*/n=read(),m=read();while(m--) G.AddEdge(read(),read());for(int i=1; i<=n; ++i)//不一定連通。。這個很坑if(!dfn[i]) Tarjan(i), pre_DFS(i,i), Solve(i,i,sz[i]);printf("%lld",Ans);return 0;
}
轉載于:https://www.cnblogs.com/SovietPower/p/9121501.html
總結
以上是生活随笔為你收集整理的LOJ.2587.[APIO2018]铁人两项Duathlon(圆方树)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。