日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[CF475E]Strongly Connected City 2

發(fā)布時(shí)間:2024/4/13 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [CF475E]Strongly Connected City 2 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題意:給一個(gè)無向圖,你需要給所有邊定向,使定向之后存在最多的點(diǎn)對(duì)$(a,b)$使得從$a$能到$b$

?

這個(gè)題,真的是太妙啦!

首先,給一個(gè)邊雙聯(lián)通分量定向之后,它可以變成一個(gè)強(qiáng)聯(lián)通分量,所以我們顯然要把每個(gè)雙聯(lián)通分量縮點(diǎn),然后處理樹上的問題

那么答案分為兩部分,一部分是雙聯(lián)通分量內(nèi)部的,一個(gè)是樹上的

設(shè)某雙聯(lián)通分量的大小為$k$,因?yàn)榻o它定向之后里面的點(diǎn)兩兩可以互達(dá),所以它對(duì)答案的貢獻(xiàn)為$k^2$

接下來找樹上的,有一個(gè)結(jié)論說,最優(yōu)解一定長這樣:存在一個(gè)點(diǎn)$s$,使得對(duì)于任意其他點(diǎn)$t$,要么$s$可以到$t$,要么$t$可以到$s$,我們把$s$作為根使整棵樹成為有根樹

感覺上是對(duì)的沒錯(cuò)我不會(huì)證

出題人這樣說:

這種玄學(xué)的東西真是令人不知所措......

回歸正題,有了這個(gè)結(jié)論,我們可以知道,$s$的每一個(gè)子樹內(nèi)的邊要么都朝向$s$,要么都是遠(yuǎn)離$s$的方向

我們可以枚舉根

記$s_i$為編號(hào)為$i$的雙聯(lián)通分量的大小,$siz_i$記以$i$為根的子樹大小

那么每個(gè)節(jié)點(diǎn)$i$的子樹內(nèi)貢獻(xiàn)的答案就是$s_i\cdot(siz_i-s_i)$

所以最后我們還得統(tǒng)計(jì)一下過根的答案,也就是決定連著根的那些邊的朝向

假設(shè)朝向根的節(jié)點(diǎn)的$siz$總和為$p$,那么過根的答案就是$p\cdot(n-s_i-p)$

所以我們要做的就是把根的子樹分成盡可能平均的兩部分,直接上背包就好了

然后,終于做完了......

#include<stdio.h> #include<string.h> struct gedge{int to,nex;bool bri; }ge[4000010]; struct tedge{int to,nex; }te[4010]; int gh[2010],th[2010],s[2010],siz[2010],dfn[2010],low[2010],col[2010],q[2010],f[2010],tot,m; void gadd(int a,int b){tot++;ge[tot].to=b;ge[tot].nex=gh[a];gh[a]=tot;ge[tot+m].to=a;ge[tot+m].nex=gh[b];gh[b]=tot+m; } void tadd(int a,int b){tot++;te[tot].to=b;te[tot].nex=th[a];th[a]=tot; } int min(int a,int b){return a<b?a:b;} int max(int a,int b){return a>b?a:b;} void bri(int x){ge[x].bri=1;if(x>m)ge[x-m].bri=1;elsege[x+m].bri=1; } void tarjan(int fa,int x){tot++;dfn[x]=low[x]=tot;for(int i=gh[x];i;i=ge[i].nex){if(dfn[ge[i].to]==0){tarjan(x,ge[i].to);low[x]=min(low[x],low[ge[i].to]);if(low[ge[i].to]>dfn[x])bri(i);}else if(dfn[ge[i].to]<dfn[x]&&ge[i].to!=fa)low[x]=min(low[x],dfn[ge[i].to]);} } void dfs(int x){for(int i=gh[x];i;i=ge[i].nex){if(col[ge[i].to]){if(col[ge[i].to]!=col[x]){tadd(col[x],col[ge[i].to]);tadd(col[ge[i].to],col[x]);}}else if(!ge[i].bri){col[ge[i].to]=col[x];dfs(ge[i].to);}} } void dfs(int fa,int x){siz[x]=s[x];for(int i=th[x];i;i=te[i].nex){if(te[i].to!=fa){dfs(x,te[i].to);siz[x]+=siz[te[i].to];}} } int main(){int N,n,i,j,k,a,b,ans,res;scanf("%d%d",&n,&m);for(i=0;i<m;i++){scanf("%d%d",&a,&b);gadd(a,b);}tot=0;tarjan(0,1);N=0;tot=0;for(i=1;i<=n;i++){if(col[i]==0){N++;col[i]=N;dfs(i);}}for(i=1;i<=n;i++)s[col[i]]++;ans=0;for(i=1;i<=N;i++){dfs(0,i);res=0;for(j=1;j<=N;j++)res+=s[j]*siz[j];q[0]=0;for(j=th[i];j;j=te[j].nex){q[0]++;q[q[0]]=te[j].to;}memset(f,0,sizeof(f));for(j=1;j<=q[0];j++){for(k=n-s[i];k>=siz[q[j]];k--)f[k]=max(f[k],f[k-siz[q[j]]]+siz[q[j]]);}res+=f[(n-s[i])>>1]*(n-s[i]-f[(n-s[i])>>1]);ans=max(ans,res);}printf("%d",ans); }

轉(zhuǎn)載于:https://www.cnblogs.com/jefflyy/p/7905970.html

總結(jié)

以上是生活随笔為你收集整理的[CF475E]Strongly Connected City 2的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。