kuangbin
专题链接:https://vjudge.net/article/752
kuangbin
专题十二 基础DP1 题解+总结:https://www.cnblogs.com/RioTian/p/13110438.html
总结:
文章目录
目录
1.Jungle Roads
原题链接:传送门
题意:
N个顶点的无向图,给你每条边的长度,要你求该图的最小生成树.其中每个点用大写字母A-Z表示.
思路:
直接kruskal
模板即可,转换输入格式.注意输入中的边没有重复边,所以无需判重.
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=30;
const int maxm=100+10;
struct Edge
{
int u,v,dist;
Edge(){}
Edge(int u,int v,int d):u(u),v(v),dist(d){}
bool operator<(const Edge &rhs)const
{
return dist<rhs.dist;
}
};
struct Kruskal
{
int n,m;
Edge edges[maxm];
int fa[maxn];
int findset(int x){ return fa[x]==-1?x:fa[x]=findset(fa[x]); }
void init(int n)
{
this->n=n;
m=0;
memset(fa,-1,sizeof(fa));
}
void AddEdge(int u,int v,int dist)
{
edges[m++]=Edge(u,v,dist);
}
int kruskal()
{
int sum=0,cnt=0;
sort(edges,edges+m);
for(int i=0;i<m;i++)
{
int u=edges[i].u, v=edges[i].v;
if(findset(u) != findset(v))
{
sum +=edges[i].dist;
fa[findset(u)] = findset(v);
if(++cnt>=n-1) return sum;
}
}
return -1;
}
}KK;
int main()
{
int n;
while(scanf("%d",&n)==1&&n)
{
KK.init(n);
for(int i=0;i<n-1;i++)
{
char s1[10],s2[10];
int k,v,d;
scanf("%s%d",s1,&k);
while(k--)
{
scanf("%s%d",s2,&d);
v=s2[0]-'A';
KK.AddEdge(i,v,d);
}
}
printf("%d\n",KK.kruskal());
}
return 0;
}
Networking
原题链接:传送门
思路:
- 完完全全的模板题,按照最小生成树的思想写代码即可。
prim 算法
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define ms(a,b) memset(a,b,sizeof a);
const int N = 55;
int n, m;
int g[N][N], d[N];
bool book[N];
int prime() {
ms(d, 0x3f); ms(book, false);
int ans = 0;
//有点类似最短路的dijstra算法
for (int i = 0; i < n; ++i) {
int t = -1;
for (int j = 1; j <= n; ++j) {
if (!book[j] && (t == -1 || d[t] > d[j])) t = j;
}
book[t] = true;//加入集合
if (i) ans += d[t];//代表不是第一个点
//改变其他点到该集合的距离
for (int j = 1; j <= n; ++j)d[j] = min(d[j], g[t][j]);
}
return ans;
}
int main() {
//freopen("in.txt", "r", stdin);
while (cin >> n && n) {
cin >> m;
//if (m == 0) { cout << 0 << endl; continue; }
ms(g, 0x3f);
int u, v, w;
for (int i = 1; i <= m; ++i) {
cin >> u >> v >> w;
g[v][u] = g[u][v] = min(g[v][u], w);//重边,选择最小值
}
cout << prime() << endl;
}
return 0;
}
kruskal算法
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define ms(a,b) memset(a,b,sizeof a);
const int maxn = 200 + 55;
const int maxm = 1e5 + 5;
struct edge {
int from, to;
int cost;
}b[maxm];
int n, m;
int f[maxn];
bool cmp(edge a, edge b) {
return a.cost < b.cost;
}
int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
int kruskal() {
int u, v;
int ans = 0, total = 0;
for (int i = 1; i <= m; ++i) {
u = find(b[i].from);
v = find(b[i].to);
if (u != v) {
ans += b[i].cost;
f[u] = v;
++total;
if (total == n - 1)
return ans;
}
}
return 0;
}
int main() {
//freopen("in.txt", "r", stdin);
int u, v, w;
while (cin >> n && n) {
cin >> m;
for (int i = 0; i <= n; ++i)f[i] = i;
for (int i = 1; i <= m; ++i) {
cin >> b[i].from >> b[i].to >> b[i].cost;
}
sort(b + 1, b + 1 + m,cmp);
cout << kruskal() << endl;
}
return 0;
}
3.Constructing Roads
原题链接:传送门
思路:
4.Agri-Net
原题链接:传送门
思路:
5.The Unique MST
原题链接:传送门
思路:
6.Highways
原题链接:传送门
思路:
7.Arctic Network
原题链接:传送门
思路:
8.Building a Space Station
原题链接:传送门
思路:
9.还是畅通工程
原题链接:传送门
思路:
10.畅通工程再续
原题链接:传送门
思路: