此题是省赛 D题 点击打开链接
比赛时没有仔细看这道题 乍一看 什么流 什么最小费用 又因为比赛前正在写网络流 当下立即以为是最小费用最大流 想套模版 发现又不是费用流 一时有没有什么好想法 后来就一直卡c了 也没有时间去看这道题目
然后听人说这道题仍旧可以用最短路去做 又仔细老板探讨了一下 感觉他所说的dijkstra 完全就是prim 只不过要自己选定费用最小的源点罢了
还有理工大大牛套最小树形图的模版过的 汗颜 根本不知道什么是最小树形图
我个人理解还是最小生成树 设置一个虚拟汇点 和每个区域连边 权值为建水库的费用 这样就把每个带费用限制的节点拆成了边 然后就是直接裸最小生成树 kruskal prim都可以
这里给出一个kruskal写的
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 310;
#define INF 0xfffffff
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
#define maxn 310
#define INF 0xfffffff
int father[maxn], n;
int Find (int x);
int Union (int x, int y);
double kruskal ();
struct node
{
int x, y, len;
friend bool operator < (node a, node b)
{
return a.len > b.len;
}
};
priority_queue <node> que;
int main ()
{
int t;
cin >> t;
while (t--)
{
cin >> n;
int x;
node q;
for (int i=1; i<=n; i++)
{
q.x = 0, q.y = i;
cin >> q.len;
que.push (q);
}
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
{
cin >> q.len;
q.x = i, q.y = j;
que.push (q);
}
cout << kruskal() << endl;
}
return 0;
}
int Find (int x)
{
return father[x] == x ? father[x] : Find (father[x]);
}
int Union (int x, int y)
{
int a = Find (x), b = Find (y);
if (a != b)
{
father[a] = b;
return 1;
}
return 0;
}
double kruskal ()
{
node s;
int i;
double sum = 0;
for (i=0; i<=n; i++)
father[i] = i;
while (que.size())
{
s = que.top (), que.pop ();
if (Union (s.x, s.y))
sum += s.len;
}
return sum;
}
然后是直接用prim不拆点的做法 dis数组里面初始化为每个区域建立水库的费用 然后直接prim
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cstdio>
#include <vector>
#include <string>
#include <iterator>
#include <cmath>
#include <deque>
#include <stack>
#include <cctype>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef long double ld;
const int N = 310;
const int INF = 0xfffffff;
const double EPS = 1e-8;
const ll MOD = 1e9 + 7;
const ld PI = acos (-1.0);
#define INFL 0x7fffffffffffffffLL
#define met(a, b) memset(a, b, sizeof(a))
#define put(a) cout << setiosflags(ios::fixed) << setprecision(a)
int g[N][N], vis[N], dis[N], cost[N];
void prim (int n);
int main ()
{
int t, n;
cin >> t;
while (t--)
{
cin >> n;
for (int i=1; i<=n; i++)
cin >> dis[i];
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
cin >> g[i][j];
prim (n);
}
return 0;
}
void prim (int n)
{
met (vis, 0);
for (int i=1; i<n; i++)
{
int minx = INF, u = 1;
for (int j=1; j<=n; j++)
{
if (!vis[j] && minx > dis[j])
minx = dis[j], u = j;
}
vis[u] = 1;
for (int j=1; j<=n; j++)
{
if (!vis[j] && dis[j] > g[u][j])
dis[j] = g[u][j];
}
}
int sum = 0;
for (int i=1; i<=n; i++)
sum += dis[i];
cout << sum << endl;
}