HDU 1102 Constructing Roads, Prim+優先隊列

來源:互聯網
上載者:User

標籤:prim   acm   hdu   圖論   

題目連結:HDU 1102 Constructing Roads

Constructing Roads

Problem DescriptionThere are N villages, which are numbered from 1 to N, and you should build some roads such that every two villages can connect to each other. We say two village A and B are connected, if and only if there is a road between A and B, or there exists a village C such that there is a road between A and C, and C and B are connected. 

We know that there are already some roads between some villages and your job is the build some roads such that all the villages are connect and the length of all the roads built is minimum.
 
InputThe first line is an integer N (3 <= N <= 100), which is the number of villages. Then come N lines, the i-th of which contains N integers, and the j-th of these N integers is the distance (the distance should be an integer within [1, 1000]) between village i and village j.

Then there is an integer Q (0 <= Q <= N * (N + 1) / 2). Then come Q lines, each line contains two integers a and b (1 <= a < b <= N), which means the road between village a and village b has been built.
 
OutputYou should output a line contains an integer, which is the length of all the roads to be built such that all the villages are connected, and this value is minimum. 
 
Sample Input
30 990 692990 0 179692 179 011 2
 
Sample Output
179
 
Sourcekicc 
RecommendEddy   |   We have carefully selected several similar problems for you:  1142 1598 1116 1269 1596  題意
有N個村子要修道路,給出了修每條道路的原始費用,現在有的道路已經修好了。我們要求的是修剩下的道路的最小費用。
分析
最小產生樹演算法,因為是鄰接矩陣,因而使用Prim方法非常方便求解,對於已經修好的道路,我們可以將他們的費用設定為0,再用Prim演算法求解即可得到。
代碼
鄰接矩陣:
#include <iostream>#include <cstdio>#include <queue>using namespace std;#define maxn 110#define INF 0xffffint g[maxn][maxn];int n;struct node{    int v, key;    friend bool operator<(node a, node b)    {        return a.key > b.key;    }};bool visited[maxn];node vx[maxn];priority_queue<node> q;void Prim(){    for(int i = 1; i <= n; i++)    {        vx[i].v = i;        vx[i].key = INF;        visited[i] = false;    }    vx[1].key = 0;    q.push(vx[1]);    while(!q.empty())    {        node nd = q.top();        q.pop();        int st = nd.v;        if(visited[st])            continue;        visited[st] = true;        for(int j = 1; j <= n; j++)        {            if(j != st && !visited[j] && vx[j].key > g[st][j])            {                vx[j].key = g[st][j];                q.push(vx[j]);            }        }    }}int main(){    int m, a, b;    while(~scanf("%d", &n))    {        for(int i = 1; i <= n; i++)        {            for(int j = 1; j <= n; j++)                scanf("%d", &g[i][j]);            g[i][i] = INF;        }        scanf("%d", &m);        while(m--)        {            scanf("%d%d", &a, &b);            g[a][b] = g[b][a] = 0;        }        Prim();        int ans = 0;        for(int i = 1; i <= n; i++)            ans += vx[i].key;        printf("%d\n", ans);    }    return 0;}

鄰接表:
#include <iostream>#include <cstdio>#include <vector>#include <queue>using namespace std;#define maxn 110  //最大頂點個數int n, m;       //頂點數,邊數struct arcnode  //邊結點{    int vertex;     //與表頭結點相鄰的頂點編號    int weight;     //串連兩頂點的邊的權值    arcnode * next; //指向下一相鄰接點    arcnode() {}    arcnode(int v,int w):vertex(v),weight(w),next(NULL) {}};struct vernode      //頂點結點,為每一條鄰接表的表頭結點{    int vex;    //當前定點編號    arcnode * firarc;   //與該頂點相連的第一個頂點組成的邊}Ver[maxn];void Init()  //建立圖的鄰接表需要先初始化,建立頂點結點{    for(int i = 1; i <= n; i++)    {        Ver[i].vex = i;        Ver[i].firarc = NULL;    }}void Insert(int a, int b, int w)  //尾插法,插入以a為起點,b為終點,權為w的邊,效率不如頭插,但是可以去重邊{    arcnode * q = new arcnode(b, w);    if(Ver[a].firarc == NULL)        Ver[a].firarc = q;    else    {        arcnode * p = Ver[a].firarc;        if(p->vertex == b)        {            if(p->weight > w)                p->weight = w;            return ;        }        while(p->next != NULL)        {            if(p->next->vertex == b)            {                if(p->next->weight > w);                    p->next->weight = w;                return ;            }            p = p->next;        }        p->next = q;    }}void Insert2(int a, int b, int w)   //頭插法,效率更高,但不能去重邊{    arcnode * q = new arcnode(b, w);    if(Ver[a].firarc == NULL)        Ver[a].firarc = q;    else    {        arcnode * p = Ver[a].firarc;        q->next = p;        Ver[a].firarc = q;    }}struct node     //儲存key值的結點{    int v;    int key;    friend bool operator<(node a, node b)   //自訂優先順序,key小的優先    {        return a.key > b.key;    }};#define INF 0xfffff    //權值上限bool visited[maxn]; //是否已經加入樹node vx[maxn];      //儲存每個結點與其父節點串連邊的權值priority_queue<node> q; //優先隊列stl實現void Prim()    //s表示根結點{    for(int i = 1; i <= n; i++) //初始化    {        vx[i].v = i;        vx[i].key = INF;        visited[i] = false;    }    vx[1].key = 0;    q.push(vx[1]);    while(!q.empty())    {        node nd = q.top();  //取隊首,記得趕緊pop掉        q.pop();        if(visited[nd.v])   //注意這一句的深意,避免很多不必要的操作            continue;        visited[nd.v] = true;        arcnode * p = Ver[nd.v].firarc;        while(p != NULL)    //找到所有相鄰結點,若未訪問,則入隊列        {            if(!visited[p->vertex] && p->weight < vx[p->vertex].key)            {                vx[p->vertex].key = p->weight;                vx[p->vertex].v = p->vertex;                q.push(vx[p->vertex]);            }            p = p->next;        }    }}int main(){    int m, a, b, x;    while(~scanf("%d", &n))    {        Init();        for(int i = 1; i <= n; i++)        {            for(int j = 1; j <= n; j++)            {                scanf("%d", &x);                if(x != 0)                    Insert2(i, j, x);            }        }        scanf("%d", &m);        while(m--)        {            scanf("%d%d", &a, &b);            Insert(a, b, 0);            Insert(b, a, 0);        }        Prim();        int ans = 0;        for(int i = 1; i <= n; i++)            ans += vx[i].key;        printf("%d\n", ans);    }    return 0;}





聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.