专栏文章
题解:P12593 沉石鱼惊旋
P12593题解参与者 3已保存评论 3
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @mip7lr7m
- 此快照首次捕获于
- 2025/12/03 07:28 3 个月前
- 此快照最后确认于
- 2025/12/03 07:28 3 个月前
Solution
这道题要求我们找到一个删除图中所有节点的顺序,使得删除过程中的总代价最小。每次删除一个节点时,代价是与该节点相连且未被删除的边的权值之和乘以这些边的数量。
开题时先看数据范围。我们发现 ,所以我们可以枚举全排列枚举删除顺序。使用打删除标记遍历每一条边来模拟题意。
至于枚举全排列可以使用 next_permutation 生成所有节点的排列顺序,每一种排列代表一种可能的删除顺序。,不会用的也可以用 DFS 搜索(同理)。
模拟删除的过程可以用维护一个数组 来记录哪些节点已经被删除。
对于当前要删除的节点 ,统计与 相连且未被删除的边的数量 和这些边的权值之和 。
再计算本次操作的代价 ,并累加到总代价中。
然后标记节点 为已删除。
最后在所有排列对应的总代价中,记录最小的那个。
本题解使用数组实现,没学过树的同学可以看看。
code
CPP#include<bits/stdc++.h>
using namespace std;
long long n,m,a[103][103],b[103][103],c[130],x,y,z,e=1e18;
bool d[103];
int main()
{
cin>>n>>m;
for(int i=0;i<m;i++)
{
cin>>x>>y>>z;
a[x][y]=a[y][x]=1;//
标记边是否存在
b[x][y]=b[y][x]=z;//存储边的权值
}
for(int i=0;i<n;i++)
c[i]=i+1;//初始化排列数组
while(next_permutation(c,c+n))//生成下一个全排列
{
for(int i=1;i<=n;i++)
d[i]=false;//重置删除标记
long long summ=0;
for(int i=0;i<n;i++)
{
long long u=c[i],cnt=0,s=0;
for(int j=1;j<=n;j++)
if(a[u][j]&&!d[j]) cnt++,s+=b[u][j];//统计边数和权值和
summ+=cnt*s;//累加代价
d[u]=true;//标记为已删除
}
e=min(summ,e);//更新最小代价
}
cout<<e;
return 0;
}
相关推荐
评论
共 3 条评论,欢迎与作者交流。
正在加载评论...