PAT-Top-1001 Battle Over Cities - Hard Version (35分)最小生成樹

1001 Battle Over Cities - Hard Version (35分)

題目傳送門:1001 Battle Over Cities - Hard Version (35分)

一、題目大意

被敵人佔領的城市,與這個城市所有相鄰的邊都無法通行。如果某一點被佔領後需要將剩餘的點相連花費的代價最大,則這點爲重點關注的點。如果產生最大代價有多個相同的點,則都要輸出。

二、解題思路

去掉一個點後,生成的最小生成樹的權重最大的情況。
注意去掉一個點後可能是不連通的圖。
打擂臺法+Prim算法求最小生成樹的權和。
可以假設完好的邊長爲0,只需要修可以修的邊。

三、AC代碼

#include<bits/stdc++.h>
using namespace std;
const int N = 501, MAX = 9999999;
int a[N][N];
int vis[N], T[N], dis[N];
int n, m,maximum = 0;
int Prim(int x){// x爲去掉的點
    int source = 1;
    if(x == 1){
        source = 2;
    }
    int res = 0;
    fill(vis+1, vis+n+1, 0);
    for(int i = 1; i <= n; i++){
        dis[i] = a[source][i];
    }
    dis[x] = 0;
    vis[source] = 1;
    for(int i = 1; i < n-1; i++){
        int u = -1, d = MAX;
        for(int j = 1; j <= n; j++){
            if(j == x)continue;
            if(vis[j] == 0 and dis[j] <= d){
                d = dis[j];
                u = j;
            }
        }
        if(u == -1)return MAX;
        vis[u] = 1;
        for(int j = 1; j <= n; j++){
            if(j == x)continue;
            if(vis[j] == 0 and dis[j] > a[u][j])dis[j] = a[u][j];
        }
    }

    for(int i = 1; i <= n; i++){
        if(dis[i] == MAX)return MAX;
        res += dis[i];
    }
    return res;
}
int main(){
    cin >> n >> m;
    int u, v, cost, status;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            a[i][j] = a[j][i] = MAX;
        }
    }
    for(int i = 1; i <= n; i++){
        a[i][i] = 0;
    }
    for(int i = 0; i < m; i++){
        cin >> u >> v >> cost >> status;
        if(status)
            a[u][v] = a[v][u] = 0;
        else
        {
            a[u][v] = a[v][u] = cost;
        }
    }
    for(int i = 1; i <= n; i++){
        // 去掉點i,然後求最小生成樹,Prim
        T[i] = Prim(i);
        maximum = max(maximum, T[i]);
    }
    bool flag = false;
    if(maximum == 0){
        cout << 0 << endl;
        return 0;
    }
    for(int i = 1; i <= n; i++){
        if(T[i] == maximum){
            if(flag){
                cout << ' ' << i;
            }else{
                flag = true;
                cout << i;
            }
        }
    }
    if(flag){
        cout << endl;
    }else{
        cout << 0 << endl;
    }
}
發佈了232 篇原創文章 · 獲贊 437 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章