Codeforces 95E Lucky Country解题报告
点击这里进入题目
题意:有N个国家,每个国家之间一共有M条无向路。国家会由路连成一个个联通块,然后问你要最少添加几条边,使最大的联通块的点的个数为一个幸运数(只包含4或7的数)。
思路:首先要做的肯定是处理联通块,可以用dfs或并查集,把每个连通块的大小都记录下来,这时候假如把每一个作为一个单独的来处理会很慢,我们要做的是把相同大小的放在一起,记录相同大小联通块的数量,再整体dp。
AC程序
//库省略
using namespace std;
const int maxn=100005,inf=1e9+7;
int fa[maxn];
ll n,m,dp[maxn];
int sz[maxn],costs[maxn];
vector<int> fas;
bool vis[maxn];
int findfa(int x)
{
if(fa[x]==x)
return x;
else
return fa[x]=findfa(fa[x]);
}
void bag(int wei,int val)
{
for(int i=n;i>=wei;i--)
{
dp[i]=min(dp[i],dp[i-wei]+val);
}
}
bool check(int xx)
{
while(xx)
{
if((xx%10)!=4 && (xx%10)!=7)
{
return 0;
}
if(xx<10)
break;
xx/=10;
}
return 1;
}
int main()
{
memset(dp,1e9+7,sizeof(dp));
cin>>n>>m;
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
fa[findfa(x)]=findfa(y);
}
for(int i=1;i<=n;i++)
{
sz[findfa(i)]++;
}
for(int i=1;i<=n;i++)
{
costs[sz[i]]++;
}
//cout<<dp[0]<<endl;
dp[0]=0;
for(int i=1;i<=n;i++)
{
if(costs[i])
{
//cout<<i<<" "<<costs[i]<<endl;
for(int j=1;j<=costs[i];j<<=1)
{
bag(j*i,j);
costs[i]-=j;
}
bag(costs[i]*i,costs[i]);
}
}
ll ans=1e9+7;
for(int i=1;i<=n;i++)
{
//cout<<i<<" "<<dp[i]<<endl;
if(check(i))
ans=min(ans,dp[i]);
}
if(ans==1e9+7)
cout<<"-1"<<endl;
else
cout<<ans-1<<endl;
return 0;
}
本文作者:~清渠~
本文链接:https://www.cnblogs.com/NightRaven/p/9341565.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
Codeforces
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
· 现代计算机视觉入门之:什么是视频
· 你所不知道的 C/C++ 宏知识
· 聊一聊 操作系统蓝屏 c0000102 的故障分析
· 不到万不得已,千万不要去外包
· C# WebAPI 插件热插拔(持续更新中)
· 会议真的有必要吗?我们产品开发9年了,但从来没开过会
· 如何打造一个高并发系统?
· 《SpringBoot》EasyExcel实现百万数据的导入导出