URAL-1982-Electrification Plan最小生成树或并查集

Electrification Plan

题意:在一个无向图中,给你几个源点,找出把所有点连接到源点后最小的消费;

可以利用并查集:

  先用结构体把每个边存起来,再按照消费大小排序。之后从消费小的到大的一个个尝试,两个点需要连接的话,连接上同时把消费也算上去;

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
const int inf = 0x3f3f3f;

using namespace std;

int n,k;
int fa[10000+7];
struct node
{
    int from,to;
    int c;
}a[10007];
bool cmp(node a,node b)
{
    return a.c<b.c;
}
void init(){
    for(int i=1;i<=n;i++)
        fa[i] = i;
}
int find(int x)
{
    if(fa[x]==x)return x;
    else return fa[x] = find(fa[x]);
}
int uni(int x,int y)
{
    if(fa[x]==-1&&fa[y]==-1)return 0;        //(**)
    int px = find(x);
    int py = find(y);
    if(px==py)return 0;
    else
    {
        fa[px] = py;
        return 1;
    }
}

int main(){
    scanf("%d%d",&n,&k);
    init();
    for(int i=1;i<=k;i++)
    {
        int x;
        scanf("%d",&x);
        fa[x]=-1;                //这个操作我其实不是很明确,我以我的理解加上了(**)这句,
    }                            //表示源点之间不用连接,但是别人写的好像不用加这句话。
    int cnt =0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            int cost;
            scanf("%d",&cost);
            if(cost==0)continue;
            a[++cnt].c=cost;
            a[cnt].from = i;
            a[cnt].to =j;
        }
    }
    sort(a+1,a+1+cnt,cmp);
    int ans = 0;
    for(int i=1;i<=cnt;i++)
    {
        if(uni(a[i].from,a[i].to))
        {
            ans += a[i].c;
        }
    }
    printf("%d\n",ans);
    return 0;
}

我自己就做了一个预处理,(直接把读入的用uni连接起来

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
const int inf = 0x3f3f3f;

using namespace std;

int n,k;
int fa[10000+7];
struct node
{
    int from,to;
    int c;
}a[10007];
bool cmp(node a,node b)
{
    return a.c<b.c;
}
void init(){
    for(int i=1;i<=n;i++)
        fa[i] = i;
}
int find(int x)
{
    if(fa[x]==x)return x;
    else return fa[x] = find(fa[x]);
}
int uni(int x,int y)
{
    int px = find(x);
    int py = find(y);
    if(px==py)return 0;
    else
    {
        fa[px] = py;
        return 1;
    }
}

int main(){
    scanf("%d%d",&n,&k);
    init();
    int last=-1;
    for(int i=1;i<=k;i++)
    {
        int x;
        scanf("%d",&x);
        if(last!=-1)
        {
            int suibian;
            suibian =uni(last,x);                //不理解别人把fa[x]=-1的操作;
            last = x;                            //自己就先预处理连接好了;
        }
        else last=x;
    }
    int cnt =0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            int cost;
            scanf("%d",&cost);
            if(cost==0)continue;
            a[++cnt].c=cost;
            a[cnt].from = i;
            a[cnt].to =j;
        }
    }
    sort(a+1,a+1+cnt,cmp);
    int ans = 0;
    for(int i=1;i<=cnt;i++)
    {
        if(uni(a[i].from,a[i].to))
        {
            ans += a[i].c;
        }
    }
    printf("%d\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/ckxkexing/p/8445610.html

时间: 2024-11-10 16:11:59

URAL-1982-Electrification Plan最小生成树或并查集的相关文章

Ural 1982 Electrification Plan (prim最小生成树)

很明显的最小生成树模板题 多点生成 [cpp] view plaincopy #include<bits/stdc++.h> using namespace std; int n,k,a; int dist[120],m[120][120]; bool p[120]; void prim() { for(int i=1;i<=n;i++) { if(!p[i]) { int Min=100020; for(int j=1;j<=n;j++) { if(p[j]&&m

timus 1982 Electrification Plan(最小生成树)

Electrification Plan Time limit: 0.5 secondMemory limit: 64 MB Some country has n cities. The government has decided to electrify all these cities. At first, power stations in k different cities were built. The other cities should be connected with t

URAL 1982. Electrification Plan(并查集)

题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1982 Some country has n cities. The government has decided to electrify all these cities. At first, power stations in k different cities were built. The other cities should be connected with the power

Timusoj 1982. Electrification Plan

http://acm.timus.ru/problem.aspx?space=1&num=1982 1982. Electrification Plan Time limit: 0.5 secondMemory limit: 64 MB Some country has n cities. The government has decided to electrify all these cities. At first, power stations in k different cities

SDUT 2933-人活着系列之Streetlights(最小生成树Kruskal+并查集实现)

人活着系列之Streetlights Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 人活着如果是为了家庭,亲情----可以说是在这个世界上最温暖人心的,也是最让人放不下的,也是我在思索这个问题最说服自己接受的答案.对,也许活着是一种责任,为了繁殖下一代,为了孝敬父母,男人要养家糊口,女人要生儿育女,就这样循环的过下去,但最终呢?还是劳苦愁烦,转眼成空呀! 为了响应政府节约能源的政策,某市要对路灯进行改革,已知该市有n个城镇,

组队赛第五场 组合隔板法+最小生成树预处理并查集

UVALive 6434 题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4445 这题正好就是大一小学期的时候好像是曦曦出的那个牛那题吧,就是要买多少块板然后正好把牛给拦完.这题也是一样,就是找最大的距离,当做隔板,依次把最大的距离去掉,最后的就是最小的了. #include<iostream> #in

URAL 1671 Anansi&#39;s Cobweb (并查集)

题意:给一个无向图.每次查询破坏一条边,每次输出查询后连通图的个数. 思路:并查集.逆向思维,删边变成加边. #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<iostream> #define inf -100000000 #define LL long long #define maxn 100005 using namespace

HDU ACM 5253 连接的管道-&gt;最小生成树(并查集)

分析:并查集实现最小生成树.不能用cin和cout(使用了ios::sync_with_stdio(false);都不行),否则TLE. #include<iostream> #include<algorithm> #include<cmath> using namespace std; #define N 1005 int father[N*N]; struct EDGE { int u,v; int len; bool operator<(const EDGE

HDU1233——还是通常工程(最小生成树,并查集)

http://acm.hdu.edu.cn/showproblem.php?pid=1233 题意:就是裸的最小生成树.这里用的是kruskal 使用的是并查集,将按距离排序的边,分别把点加到集合里.节点存在在集合里说明是环路. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,s,k; int par[10