kuangbin专题6 最小生成树 POJ2349/POJ3026/POJ1679

写在前面:

最近几个月(三四个月吧)都没有好好敲代码,没有好好训练。
一个是疫情影响,下半年的比赛数量变少了,参赛的名额变少了,参赛的概率变小了,之前付出一个又一个假期和周末的努力可能得不到一个好的交代,所以整个人比较迷茫比较烦躁。
另一个是自己的原因吧。

放假之后想出去走走,用一种仪式感的旅行结束糟糕了一个学期的心情,奈何一搜天气,想去的地方全是连绵阴雨,加上当时bj疫情突然严重,整的我爸也不让我出门了。只得向后延。希望这个假期还有机会出去。

放假之后一直在刷B站 知乎 微博 神武等等等等 甚至下载了好久没玩的飞车 开始和好朋友一块打王者……
我企图用几天的堕落去唤醒自己内心深处的愧疚,然后奋起学习,然后堕落了几天之后我发现,我适应了!舒适圈竟然那么舒适!打游戏和看剧太香了!!!(卒

身边的好朋友,有大二的也有大三的,大三的居多。
大二的都在三下乡大创打游戏追剧。
大三的 有的在忙活夏令营,忙推免,有的在争取实习,有的在准备考研,总之就感觉很忙。
这些大三老友每个人都羡慕我:“你才大二啊,真好 可以玩了”
我:………………

下面是这个假期刚刚开始刷的题。虽然大部分都是板子题,但也有一定的作用,希望这些算是一个好的开始。继续加油吧!

暑假快乐,祝安。
在这里插入图片描述
这套题前几道都是板子就不放了。
放三道板子+变形

POJ2349 Arctic Network

题意:给你m和n,再给你n行坐标,每个坐标都是信号基站,两个基站之间可以通讯的条件是 距离不大于某个值D,或者两个点都拥有卫星
需要求解的是:在有m个卫星的情况下,问你D最小为多少,可以满足任两个基站之间可以通讯。
思路:这个D看似很复杂,但是转变一下,就是把最长的m-1条边都用卫星来实现,剩下的最长边即为D。
这个方法总感觉怪怪的,要是最长的两条边占据了四个端点怎么办呢。。。
不知道。。。再想想啊再想想。
用prim或者kruscal求出MST的每条边,然后存下来,看看第m大的边的长度即可。
要注意判断一下n==m的情况,就是说全都可以用卫星实现通讯,那D自然是0.00(卫星niubility!)。
下面是AC代码


#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define inf 0x3f3f3f3f
#define sd(a) scanf("%d",&a)
#define sdd(a,b) scanf("%d%d",&a,&b)
#define cl(a,b) memset(a,b,sizeof(a))
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define sddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define dbg() printf("aaa\n")
using namespace std;
const int maxn=1010;
int n,m,cnt;//n点数 m基站数
struct node{
    int x,y;
}a[maxn];
struct Side{
    int u,v,next;
    double val;
}side[maxn*maxn];
int head[maxn],vis[maxn];
double dis[maxn];
priority_queue<double> q;
void prim(){
    for(int i=1;i<=n;i++) dis[i]=1e18;
    cl(vis,false);
    dis[1]=0;
    vis[1]=true;
    for(int i=head[1];i!=-1;i=side[i].next){
        int v=side[i].v;
        double val=side[i].val;
        if(dis[v]>val) dis[v]=val;
    }
    rep(i,1,n-1){
        double minn=1e18;
        int p;
        rep(j,1,n){
            if(!vis[j]&&minn>dis[j]){
                minn=dis[j];
                p=j;
            }
        }
        vis[p]=true;
        for(int j=head[p];j!=-1;j=side[j].next){
            int v=side[j].v;
            double val=side[j].val;
            if(!vis[v]&&dis[v]>val){
                dis[v]=val;
            }
        }
        q.push(minn);
    }
}
void add(int u,int v,double val){
    side[cnt].v=v;
    side[cnt].val=val;
    side[cnt].next=head[u];
    head[u]=cnt++;
}
int main() {
	int T;
    sd(T);
    while(T--){
        sdd(m,n);
        while(!q.empty()) q.pop();
        cl(head,-1);
        cnt=0;
        rep(i,1,n){
            sdd(a[i].x,a[i].y);
        }
        cnt=0;
        rep(i,1,n){
            rep(j,1,n){
                if(i==j) continue;
                int dx=abs(a[i].x-a[j].x);
                int dy=abs(a[i].y-a[j].y);
                add(i,j,sqrt((double)(dx*dx+dy*dy)));
                add(j,i,sqrt((double)(dx*dx+dy*dy)));
            }
        }
        prim();
        for(int i=1;i<=m-1;i++) q.pop();
        if(!q.empty())
            printf("%.2lf\n",q.top());
        else printf("0.00\n");
    }
	return 0;
}

下面是题目描述
The Department of National Defence (DND) wishes to connect several northern outposts by a wireless network. Two different communication technologies are to be used in establishing the network: every outpost will have a radio transceiver and some outposts will in addition have a satellite channel.
Any two outposts with a satellite channel can communicate via the satellite, regardless of their location. Otherwise, two outposts can communicate by radio only if the distance between them does not exceed D, which depends of the power of the transceivers. Higher power yields higher D but costs more. Due to purchasing and maintenance considerations, the transceivers at the outposts must be identical; that is, the value of D is the same for every pair of outposts.

Your job is to determine the minimum D required for the transceivers. There must be at least one communication path (direct or indirect) between every pair of outposts.
Input
The first line of input contains N, the number of test cases. The first line of each test case contains 1 <= S <= 100, the number of satellite channels, and S < P <= 500, the number of outposts. P lines follow, giving the (x,y) coordinates of each outpost in km (coordinates are integers between 0 and 10,000).
Output
For each case, output should consist of a single line giving the minimum D required to connect the network. Output should be specified to 2 decimal points.
Sample Input
1
2 4
0 100
0 300
0 600
150 750
Sample Output
212.13

POJ3026 Borg Maze

这个题超级迷超级迷!!!我感觉这个题有问题!!!
答案给的也有问题。。。总之俩样例就很莫名其妙 第二个应该是12 但是莫名其妙跑出结果就是11 真的!莫名其妙 或者说咱没明白题意…
题意:就是个二维平面的最小生成树,只要求出每个字母到其他所有字母的最短路然后套板子即可。
求每个字母到其他字母最短路的时候需要用到BFS,而不是简单的横纵坐标差之和。
并且在BFS时要一重循环BFS 而不要两重循环去BFS 会T!!!
具体步骤是
1、读入地图
2、从头到尾扫一遍地图,按遇到的顺序给每个字母编号并放入结构体数组中(S和A一视同仁),然后开另一个图记录某个坐标对应点的编号是多少。
3、遍历一遍结构体数组,对于每个坐标都BFS一遍,得到该点到剩余点的距离,存入新图中,该图即邻接矩阵图!
4、对求出来的邻接矩阵图进行prim。
总之写的挺乱的自己。
以后有时间一定重写一遍(下次一定)。
下面是AC代码。

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define inf 0x3f3f3f3f
#define sd(a) scanf("%d",&a)
#define sdd(a,b) scanf("%d%d",&a,&b)
#define cl(a,b) memset(a,b,sizeof(a))
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define sddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define dbg() printf("aaa\n")
using namespace std;
const int maxn=110;
int n,m,cnt;
char g[maxn][maxn];//原图!!!
bool con[maxn][maxn];//bfs时这个点有没有搜过
int mp[maxn][maxn];//距离
int dis[maxn];//prim用的dis数组
bool vis[maxn];//prim用的vis数组
int ins[maxn][maxn];//坐标映射成编号!!!
struct node{
    int x,y,step;
}a[maxn];
int dir[4][2]={1,0,-1,0,0,-1,0,1};
bool judge(int x,int y){
    if(x>=1&&x<=n&&y>=1&&y<=m&&g[x][y]!='#'&&!con[x][y])
        return true;
    return false;
}
void bfs(int a,int b){
    //找到ab开始的到所有的最短长度
    int id=ins[a][b];
    rep(i,1,n)
        rep(j,1,m)
            con[i][j]=false;
    con[a][b]=true;//很重要!
    queue<node> q;
    while(!q.empty()) q.pop();
    node tp;
    tp.x=a,tp.y=b,tp.step=0;
    q.push(tp);
    while(!q.empty()){
        tp=q.front();
        q.pop();
        int id1=ins[tp.x][tp.y];
        if(g[tp.x][tp.y]=='A'||g[tp.x][tp.y]=='S'){
            mp[id][id1]=mp[id1][id]=tp.step;
            //printf("%d %d %d\n",id,id1,tp.step);
        }
        for(int i=0;i<4;i++){
            node tp1;
            tp1.x=tp.x+dir[i][0];
            tp1.y=tp.y+dir[i][1];
            tp1.step=tp.step+1;
            if(judge(tp1.x,tp1.y)){
                q.push(tp1);
                con[tp1.x][tp1.y]=true;
            }
        }
    }
    return;
}
int prim(){
    cl(vis,0);
    rep(i,1,cnt){
        dis[i]=mp[1][i];
    }
    vis[1]=true;
    int ans=0;
    for(int i=1;i<=cnt-1;i++){
        int minn=inf,p;
        for(int j=1;j<=cnt;j++){
            if(!vis[j]&&minn>dis[j]){
                minn=dis[j];
                p=j;
            }
        }
        vis[p]=true;
        for(int j=1;j<=cnt;j++){
            if(!vis[j]&&dis[j]>mp[p][j]){
                dis[j]=mp[p][j];
            }
        }//printf("%d %d\n",p,minn);
        ans+=minn;
    }
    return ans;
}
int main() {
	int T;
    sd(T);
    while(T--){
        sdd(m,n);gets(g[0]);
        rep(i,1,n){
            gets(g[i]+1);
            //puts(g[i]+1);
        }
        cnt=0;
        rep(i,1,n){//记录下所有的SA结点
            rep(j,1,m){
                if(g[i][j]=='S'||g[i][j]=='A'){
                    cnt++;
                    a[cnt].x=i,a[cnt].y=j;//存下所有的坐标位置
                    //映射一下
                    ins[i][j]=cnt;
                }
            }
        }
        rep(i,1,cnt){
            mp[i][i]=0;
            bfs(a[i].x,a[i].y);
        }
        printf("%d\n",prim());
    }
	return 0;
}

下面是题面:
The Borg is an immensely powerful race of enhanced humanoids from the delta quadrant of the galaxy. The Borg collective is the term used to describe the group consciousness of the Borg civilization. Each Borg individual is linked to the collective by a sophisticated subspace network that insures each member is given constant supervision and guidance.

Your task is to help the Borg (yes, really) by developing a program which helps the Borg to estimate the minimal cost of scanning a maze for the assimilation of aliens hiding in the maze, by moving in north, west, east, and south steps. The tricky thing is that the beginning of the search is conducted by a large group of over 100 individuals. Whenever an alien is assimilated, or at the beginning of the search, the group may split in two or more groups (but their consciousness is still collective.). The cost of searching a maze is definied as the total distance covered by all the groups involved in the search together. That is, if the original group walks five steps, then splits into two groups each walking three steps, the total distance is 11=5+3+3.
Input
On the first line of input there is one integer, N <= 50, giving the number of test cases in the input. Each test case starts with a line containg two integers x, y such that 1 <= x,y <= 50. After this, y lines follow, each which x characters. For each character, a space '' stands for an open space, a hash mark#’’ stands for an obstructing wall, the capital letter A'' stand for an alien, and the capital letterS’’ stands for the start of the search. The perimeter of the maze is always closed, i.e., there is no way to get out from the coordinate of the ``S’’. At most 100 aliens are present in the maze, and everyone is reachable.
Output
For every test case, output one line containing the minimal cost of a succesful search of the maze leaving no aliens alive.

POJ1679 The Unique MST

题意:明确告诉你是找唯一的最小生成树
让你判断给出的一个图是否有唯一的最小生成树,有的话输出权值,没有的话输出Not Unique!
思路:自己真的不会啊,就和之前最短路判断是否唯一一样,然后百度了题解看了一下思路。
发现其实很简单:求出最小生成树之后,枚举每一条边,标记这条边不能用,在此基础上再去建立最小生成树,看生成的最小生成树权值是否和原来一样。
如果一样,说明不唯一,否则唯一
下面是AC代码:

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define inf 0x3f3f3f3f
#define sd(a) scanf("%d",&a)
#define sdd(a,b) scanf("%d%d",&a,&b)
#define cl(a,b) memset(a,b,sizeof(a))
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define sddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define dbg() printf("aaa\n")
using namespace std;
//判断最小生成树是否唯一
//先求出最小生成树  然后依次删掉每一条边
const int maxn=110;
int n,m;
struct Side{
    int u,v,val;
    bool operator<(const Side &oth)const{
        return val<oth.val;
    }
}a[maxn*maxn];
int rec[maxn];//记录最小生成树的边有哪些
int pre[maxn];
int find(int x){
    if(x==pre[x]) return x;
    return pre[x]=find(pre[x]);
}
void join(int a,int b){
    int fa=find(a),fb=find(b);
    pre[fa]=fb;
    return;
}
int kruscal(int id){//被删除的边的id
    int ans=0;
    int cnt=0;
    for(int i=1;i<=m;i++){
        if(i==id) continue;
        int fa=find(a[i].u),fb=find(a[i].v);
        if(fa!=fb){
            join(fa,fb);
            ans+=a[i].val;
            cnt++;
        }
        if(cnt==n-1) break;
    }
    if(cnt==n-1) return ans;
    return -1;//没有最小生成树了
}
int main() {
	int T;
    sd(T);
    while(T--){
        sdd(n,m);
        rep(i,1,n) pre[i]=i;
        rep(i,1,m){
            sddd(a[i].u,a[i].v,a[i].val);
        }
        sort(a+1,a+m+1);
        int cnt=0;
        int ans=0;
        for(int i=1;i<=m;i++){
            int fa=find(a[i].u),fb=find(a[i].v);
            if(fa!=fb){
                join(fa,fb);
                cnt++;
                rec[cnt]=i;
                ans+=a[i].val;
            }
            if(cnt==n-1) break;
        }
        bool flag=false;//不存在
        for(int i=1;i<=n-1;i++){//枚举删除的边
            rep(i,1,n) pre[i]=i;
            int ans1=kruscal(rec[i]);
            //printf("%d %d\n",ans1,ans);
            if(ans1==ans){
                flag=true;
                break;
            }
        }
        if(!flag){
            printf("%d\n",ans);
        }else{
            printf("Not Unique!\n");
        }
    }
	return 0;
}

Given a connected undirected graph, tell if its minimum spanning tree is unique.

Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V’, E’), with the following properties:

  1. V’ = V.
  2. T is connected and acyclic.

Definition 2 (Minimum Spanning Tree): Consider an edge-weighted, connected, undirected graph G = (V, E). The minimum spanning tree T = (V, E’) of G is the spanning tree that has the smallest total cost. The total cost of T means the sum of the weights on all the edges in E’.
Input
The first line contains a single integer t (1 <= t <= 20), the number of test cases. Each case represents a graph. It begins with a line containing two integers n and m (1 <= n <= 100), the number of nodes and edges. Each of the following m lines contains a triple (xi, yi, wi), indicating that xi and yi are connected by an edge with weight = wi. For any two nodes, there is at most one edge connecting them.
Output
For each input, if the MST is unique, print the total cost of it, or otherwise print the string ‘Not Unique!’.
Sample Input
2
3 3
1 2 1
2 3 2
3 1 3
4 4
1 2 2
2 3 2
3 4 2
4 1 2
Sample Output
3
Not Unique!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值