您的位置:首页 > 其它

最小生成树 2016.7.20

2016-06-07 15:24 351 查看

1、UVa 10048 Audiophobia

参考:http://blog.csdn.net/shuangde800/article/details/7985085

题意:

c1到c2的每条路径的声强为这条路径所包含的边的最大权值

求c1到c2的声强最小的一条路径的声强

解题思路:

模拟kruskal的过程

先将所有的边按权值递增进行排序,再一条边一条边的加

每加入一次边,就去判断需要查询的那条路径的起点和终点是否在同一个集合里

 若在同一个集合里了,那么那条路径中的最大值便是当前加入的这条边的权值,且这条路径是声强最小的一个

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>

using namespace std;

const int INF = 0x3f3f3f3f;
int C, S, Q;

struct Node {
int s, e;
int val;
};

struct Query {
int s, e;
};

int pre[110];
Node node[1010];
Query query[10010];
int ans[10010];
bool vis[10010];
int Rank[110];

int cmp_num(const void* a, const void* b);
int Find_Root(int x);

int main()
{
int Case = 0;
while (scanf("%d%d%d", &C, &S, &Q) != EOF && !(C == 0 && S == 0 && Q == 0)) {
for (int i = 0; i < S; ++i) {
scanf("%d%d%d", &node[i].s, &node[i].e, &node[i].val);
}
for (int i = 0; i < Q; ++i) {
scanf("%d%d", &query[i].s, &query[i].e);
}
++Case;
if (Case > 1) {
printf("\n");
}
printf("Case #%d\n", Case);
for (int i = 1; i <= C; ++i) {
pre[i] = i;
Rank[i] = 0;
}
qsort(node, S, sizeof(node[0]), cmp_num);
memset(ans, -1, sizeof(ans));
memset(vis, false, sizeof(vis));
for (int i = 0; i < S; ++i) {
int nx = Find_Root(node[i].s);
int ny = Find_Root(node[i].e);
if (nx != ny) {
if (Rank[nx] > Rank[ny]) {
pre[ny] = nx;
} else {
if (Rank[nx] == Rank[ny]) {
++Rank[ny];
}
pre[nx] = ny;
}
for (int j = 0; j < Q; ++j) {
if (!vis[j]) {
int qx = Find_Root(query[j].s);
int qy = Find_Root(query[j].e);
if (qx == qy) {
vis[j] = true;
ans[j] = node[i].val;
}
}
}
}
}
for (int i = 0; i < Q; ++i) {
if (ans[i] != -1) {
printf("%d\n", ans[i]);
} else {
printf("no path\n");
}
}
}
return 0;
}

int cmp_num(const void* a, const void* b)
{
Node* x = (Node*)a;
Node* y = (Node*)b;
return (x->val - y->val) > 0 ? 1 : -1;
}

int Find_Root(int x)
{
int r = x;
while (pre[r] != r) {
r = pre[r];
}
while (pre[x] != r) {
int t = pre[x];
pre[x] = r;
x = t;
}
return r;
}

2、POJ 1258 Agri-Net

Prim

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;

const int mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 100 + 10;
int Graph[maxn][maxn];
int lowcost[maxn];
bool vis[maxn];
int N;

int Prim(void);

int main()
{
while (scanf("%d", &N) != EOF) {
for (int i = 1; i <= N; ++i) {
for (int j = 1; j <= N; ++j) {
scanf("%d", &Graph[i][j]);
}
}
printf("%d\n", Prim());
}
return 0;
}

int Prim(void)
{
memset(vis, false, sizeof(vis));
int sum = 0;
for (int i = 2; i <= N; ++i) {
lowcost[i] = Graph[1][i];
}
for (int i = 0;  i < N-1; ++i) {
int Min = INF;
int t;
for (int j = 2; j <= N; ++j) {
if (!vis[j] && lowcost[j] < Min) {
Min = lowcost[j];
t = j;
}
}
if (Min == INF) {
break;
}
vis[t] = true;
sum += lowcost[t];
for (int j = 2; j <= N; ++j) {
if (!vis[j] && lowcost[j] > Graph[t][j]) {
lowcost[j] = Graph[t][j];
}
}
}
return sum;
}


3、HDU 1102 Constructing Roads

Prim

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int INF = 0x3f3f3f3f;
const int maxn = 100 + 5;
int Map[maxn][maxn];
int lowcost[maxn];
bool vis[maxn];
int N;
int sum;

void Prime(void);

int main()
{
while (cin>>N) {
memset(vis, false, sizeof(vis));
for (int i=1; i<=N; ++i) {
for (int j=1; j<=N; ++j) {
cin>>Map[i][j];
}
}
int Q;
cin>>Q;
int a, b;
for (int i=0; i<Q; ++i) {
cin>>a>>b;
Map[a] = Map[b][a] = 0;
}
sum = 0;
Prime();
cout<<sum<<endl;
}
return 0;
}

void Prime(void)
{
for (int i=2; i<=N; ++i) {
lowcost[i] = Map[1][i];
}
for (int i=2; i<=N; ++i) {
int Min = INF;
int t;
for (int j=2; j<=N; ++j) {
if (!vis[j] && Min > lowcost[j]) {
Min = lowcost[j];
t = j;
}
}
if (Min == INF) {
break;
}
sum += Min;
vis[t] = true;
for (int j=2; j<=N; ++j) {
if (!vis[j] && lowcost[j] > Map[t][j]) {
lowcost[j] = Map[t][j];
}
}
}
}


[b]4、POJ 1251 Jungle Roads

Prim

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int INF = 0x3f3f3f3f;
const int maxn = 40;
int Map[maxn][maxn];
int lowcost[maxn];
bool vis[maxn];
int n;
int sum;

void Prime(void);

int main()
{
while (cin>>n && n!=0) {
memset(vis, false, sizeof(vis));
for (int i=1; i<=n; ++i) {
for (int j=1; j<=n; ++j) {
if (i == j) {
Map[i][j] = 0;
} else {
Map[i][j] = INF;
}
}
}
char c;
int num1, num2;
for (int i=0; i<n-1; ++i) {
cin>>c>>num1;
int s = c - 'A' + 1;
for (int j=0; j<num1; ++j) {
cin>>c>>num2;
int e = c - 'A' + 1;
Map[s][e] = Map[e][s] = num2;
}
}
sum = 0;
Prime();
cout<<sum<<endl;
}
return 0;
}

void Prime(void)
{
for (int i=1; i<=n; ++i) {
lowcost[i] = Map[1][i];
}
for (int i=2; i<=n; ++i) {
int Min = INF;
int t;
for (int j=2; j<=n; ++j) {
if (!vis[j] && Min > lowcost[j]) {
t = j;
Min = lowcost[j];
}
}
if (Min == INF) {
break;
}
sum += Min;
vis[t] = true;
for (int j=2; j<=n; ++j) {
if (!vis[j] && lowcost[j] > Map[t][j]) {
lowcost[j] = Map[t][j];
}
}
}
}


5、HDU 5723 Abandoned country

解题思路:

http://bestcoder.hdu.edu.cn/blog/2016-multi-university-training-contest-1-solutions-by-hit/

标程:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
using namespace std;
#define N 100010
struct node {
int u, v, w;
node() {}
node(int _u, int _v, int _w):u(_u), v(_v), w(_w) {}
};
struct Node{
int v,len;
Node(){}
Node(int _v, int _len):v(_v), len(_len){}
};
vector<Node>vet
;
vector<node> edge;
int n, m, f
;
double dp
;
int sum
;
bool cmp(const node &x, const node &y) {
return x.w < y.w;
}
int find_set(int x) {
if (f[x] == x) return x;
return f[x] = find_set(f[x]);
}
long long Kruskal() {
sort(edge.begin(), edge.end(), cmp);
for (int i = 1; i <= n; i++) f[i] = i;
long long ans = 0;
for (int i = 0, u, v, w; i < (int)edge.size(); i++)
{
u = edge[i].u, v = edge[i].v, w = edge[i].w;
u = find_set(u), v = find_set(v);
if (u == v) continue;
f[u] = v;
ans += (long long)w;
vet[edge[i].u].push_back(Node(edge[i].v,w));
vet[edge[i].v].push_back(Node(edge[i].u,w));
}
return ans;
}
void dfs(int root,int father)
{
sum[root] = 1;
for(int i = 0;i < (int)vet[root].size();i++)
{
int son = vet[root][i].v;
int len = vet[root][i].len;
if(son == father)continue;
dfs(son,root);
sum[root] += sum[son];
dp[root] += dp[son] + ((double)sum[son] * (n - sum[son])) * len;
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d", &n, &m);
edge.clear();
for (int i = 0, a, b, c; i < m; i++)
{
scanf("%d%d%d", &a, &b, &c);
edge.push_back(node(a, b, c));
}
for(int i = 1;i <= n;i++)vet[i].clear();
memset(sum,0,sizeof(sum));
memset(dp,0,sizeof(dp));
long long ans = Kruskal();
dfs(1,0);
long long s = (long long)n * (n - 1) / 2;
printf("%I64d %.2f\n",ans,dp[1] / (double)s);
}
return 0;
}


看官方的标程和解题思路看了一上午才敲出来,刚开始也想到统计每条边用过的次数乘以边权然后加起来,最后除以总数,但是做法完全错误

第一次多校赛一题未出,为什么会有我这么菜的人...%%%大牛们

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;

const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 1e5 + 10;
int n, m;

struct Node {
int s, e;
int dis;
};

struct V {
int key, dis;
};

vector<V> v[maxn];
Node node[1000010];
int pre[maxn];
int sum[maxn];
double ans[maxn];

int Find_Root(int x);
bool cmp(Node a, Node b);
void dfs(int root, int father);

int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
int T;
scanf("%d", &T);
while (T--) {
memset(sum, 0, sizeof(sum));
memset(ans, 0, sizeof(ans));
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) {
v[i].clear();
}
for (int i = 1; i <= n; ++i) {
pre[i] = i;
}
for (int i = 0; i < m; ++i) {
scanf("%d%d%d", &node[i].s, &node[i].e, &node[i].dis);
}
sort(node, node+m, cmp);
ull Min = 0;
for (int i = 0; i < m; ++i) {
int ra = Find_Root(node[i].s), rb = Find_Root(node[i].e);
if (ra != rb) {
Min += node[i].dis;
pre[ra] = rb;
V t;
t.key = node[i].e, t.dis = node[i].dis;
v[node[i].s].push_back(t);
t.key = node[i].s;
v[node[i].e].push_back(t);
}
}
dfs(1, 0);
ull t = (ull)n * (n-1) / 2;
printf("%I64d %.2f\n", Min, ans[1] / (1.0 * t));
}
return 0;
}

void dfs(int root, int father)
{
sum[root] = 1;
for (int i = 0; i < (int)v[root].size(); ++i) {
int son = v[root][i].key;
int dis = v[root][i].dis;
if (son != father) {
dfs(son, root);
sum[root] += sum[son];
ans[root] += ans[son] + 1.0 * sum[son] * (n - sum[son]) * dis;
}
}
}

int Find_Root(int x)
{
int r = x;
while (pre[r] != r) {
r = pre[r];
}
while (pre[x] != r) {
int t = pre[x];
pre[x] = r;
x = t;
}
return r;
}

bool cmp(Node a, Node b)
{
return (a.dis < b.dis);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: