题解:P12593 沉石鱼惊旋
Solution
今天比赛挂分了,写篇题解弥补一下吧。
这道题要求我们找到一个删除图中所有节点的顺序,使得删除过程中的总代价最小。每次删除一个节点时,代价是与该节点相连且未被删除的边的权值之和乘以这些边的数量。
开题时先看数据范围。我们发现
至于枚举全排列可以使用 next_permutation 生成所有节点的排列顺序,每一种排列代表一种可能的删除顺序。,不会用的也可以用 DFS 搜索(同理)。
模拟删除的过程可以用维护一个数组
对于当前要删除的节点
再计算本次操作的代价
然后标记节点
最后在所有排列对应的总代价中,记录最小的那个。
本题解使用数组实现,没学过树的同学可以看看。
code
#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;
}