CF475E Strongly Connected City 2 题解
题目链接:CF475E Strongly Connected City 2
首先边双之内是可以有方法定向使其变成任意两个点之间都可达的,证明感性理解。将边双缩完点后图变为一棵树,观察可得最优点一定是带权重心,有些子树连向他然后他连向剩下的子树,子树内的连边方向和子树的根和重心的连边一样。这样是最接近 $ frac{n^2}{4} $ 的。
代码:
#include<bits/stdc++.h>
#define time(null) chrono::steady_clock::now().time_since_epoch().count()
#define int long long
#define uint unsigned long long
#define debug() cout<<"come here\n"
#define INF 0x3f3f3f3f3f3f3f3f
#define pii pair<int,int>
#define pb push_back
#define Code return
#define by 0
#define MCYYDS ;
using namespace std;
int qpow(int a,int b,int p=INF){int ret=1;while(b){if(b&1)ret=(ret*a)%p;a=(a*a)%p;b>>=1;}return ret;}
inline int read(){int ret=0,f=1;char ch=getchar();while(ch<'0'||ch>'9')f=(ch=='-'?-1:f),ch=getchar();while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+(ch^48),ch=getchar();return ret*f;}
inline void write(int x){if(x<0){putchar('-');write(-x);return ;}if(x>9)write(x/10);putchar((char)(x%10+48));}
inline void writech(int x,char ch){write(x);putchar(ch);}
int dfn[2005],low[2005],sz[2005],col[2005],s[2005],tot,cnt,sum,cur;
vector<int> e[2005],g[2005];
bitset<2005> dp;
stack<int> stk;
void dfs(int u,int fa)
{
dfn[u]=low[u]=++tot;
stk.push(u);
for(auto v:e[u])
{
if(v==fa)continue;
if(!dfn[v])
{
dfs(v,u);
low[u]=min(low[u],low[v]);
}
else low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
++cnt;
while(stk.size()&&stk.top()!=u)
{
s[cnt]++;
col[stk.top()]=cnt;
stk.pop();
}
s[cnt]++;
col[stk.top()]=cnt;
stk.pop();
sum+=s[cnt]*s[cnt];
}
}
void dfs2(int u,int fa)
{
sz[u]=s[u];
for(auto v:g[u])
{
if(v==fa)continue;
dfs2(v,u);
sz[u]+=sz[v];
}
cur+=s[u]*(sz[u]-s[u]);
}
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);
// cout.tie(0);
int n=read(),m=read();
for(int i=1;i<=m;i++)
{
int u=read(),v=read();
e[u].pb(v);
e[v].pb(u);
}
for(int i=1;i<=n;i++)
{
if(!dfn[i])dfs(i,0);
}
for(int i=1;i<=n;i++)
{
for(auto v:e[i])
{
if(col[i]!=col[v])
{
g[col[i]].pb(col[v]);
}
}
}
int ans=0;
for(int i=1;i<=cnt;i++)
{
memset(sz,0,sizeof(sz));
cur=0;
dfs2(i,0);
dp.reset();
dp[0]=1;
for(auto v:g[i])
{
dp|=(dp<<sz[v]);
}
for(int j=(sz[i]-s[i])/2;j>=0;j--)
{
if(dp[j])
{
cur+=j*(n-j-s[i]);
break;
}
}
ans=max(ans,cur);
}
writech(ans+sum,'\n');
Code by MCYYDS
}

浙公网安备 33010602011771号