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!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章