jzoj3896-战争游戏【tarjan,割点,点双联通分量】
生活随笔
收集整理的這篇文章主要介紹了
jzoj3896-战争游戏【tarjan,割点,点双联通分量】
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
正題
題目大意
求每個點是多少個點對之間路徑的必經(jīng)點。
解題思路
首先若一個點是在點不是割點,那么答案就是n?1n-1n?1,因為這個點不是除了它自己以為任何點對的必經(jīng)點。
之后我們記錄每個可以割掉的聯(lián)通分量的大小。對于一個割點,是兩種路徑的必經(jīng)點。
分開計算就好了。
codecodecode
#include<cstdio> #include<stack> #include<queue> #include<cstring> #define N 50010 using namespace std; struct line{int to,next; }a[N*4]; int tot,ls[N],siz[N],dfn[N],low[N],num,n,ans[N],m; bool v[N]; void addl(int x,int y) {a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot; } void tarjan(int x,int fa)//tarjan {dfn[x]=low[x]=++num;int L=0;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;v[y]=0;if(!dfn[y]){tarjan(y,x);siz[x]+=siz[y];if(dfn[x]<=low[y])L+=siz[y];v[y]=1;}if(y!=fa)low[x]=min(low[y],low[x]);}//以上求low和dfn以判斷割點int A=0,B=0;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(dfn[x]<=low[y]&&v[y]){A+=(L-siz[y])*siz[y];//點內(nèi)互相到達B+=(n-L-1)*siz[y];//外連內(nèi)}}A/=2;ans[x]=A+B+n-1; } int main() {freopen("data.in","r",stdin);freopen("data.out","w",stdout);scanf("%d%d",&n,&m);for (int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);addl(x,y);addl(y,x);}num=0;for(int i=1;i<=n;i++)siz[i]=1;tarjan(1,0);for(int i=1;i<=n;i++)printf("%d\n",ans[i]); }總結(jié)
以上是生活随笔為你收集整理的jzoj3896-战争游戏【tarjan,割点,点双联通分量】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 惠存是什么意思 惠存语义解析
- 下一篇: 天涯明月刀傅红雪是谁的儿子 你看过这个电