您的位置:首页 > 其它

买礼物

2017-10-26 23:20 141 查看

 原题链接:https://www.luogu.org/problem/show?pid=1194#sub

日常数组开小(1/1)。

一个裸的最小生成树。跑一遍最小生成树记录一下所花价钱,然后扫一下father数组把没优惠的补上,输出就好了。

参考代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define maxn 500000
using namespace std;
struct Edge{
int from,to,dis;
bool operator<(const Edge &rhs)const{
return dis < rhs.dis;
}
};
inline int read(){
int num = 0;
char c;
bool flag = false;
while ((c = getchar()) == ' ' || c == '\n' || c == '\r');
if (c == '-')
flag = true;
else
num = c - '0';
while (isdigit(c = getchar()))
num = num * 10 + c - '0';
return (flag ? -1 : 1) * num;
}
Edge edge[maxn];
int father[maxn];
int n,m;
int tot = 0;
int ans,totedge,readnum;
int find(int x){
if (father[x] == x)
return father[x];
else
return find(father[x]);
}
void merge(int x,int y){
father[find(y)] = find(x);
}
bool check(int x,int y){
return find(x) == find(y);
}
int main(){
n = read();m = read();
for (register int i=1;i<=m;i++)
father[i] = i;
for (register int i=1;i<=m;i++)
for (register int j=1;j<=m;j++){
readnum = read();
if (readnum!=0){
edge[++tot].from = i;
edge[tot].to = j;
edge[tot].dis = readnum;
}
}
sort(edge+1,edge+tot+1);
for (register int i=1;i<=tot;i++){
int u = edge[i].from;
int v = edge[i].to;
if (!check(u,v)){
totedge++;
ans += edge[i].dis;
merge(u,v);
if (totedge == m-1)
break;
}
}
for (register int i=1;i<=n;i++)
if (father[i] == i)
ans += n;
printf("%d\n",ans);
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: