POJ 1679 The Unique MST

 /*
<1>要求:这道题的要求是给定一个无向联通图,判断这个图的最小生成树MST是不是唯一的,如果是唯一的则
打印出最小值,如果不是唯一的给出提示
<2>分析:采用Kruskal算法来计算最小生成树,仔细分析其过程不难发现这个图的MST不唯一的充分必要条件是
在Kruskal运算过程中如果选中的当前边a构成了环,且在所有包含这条边的环中如果存在和这条边权值相等的
边b,则MST不唯一,因为总是可以利用a取代b构成一个新的MST.算法清楚了, 那么实现最难的地方就是找环了
<3>实现:为了提高计算的速度,我将边保存两份,一份用结构表示,存储所有边,用来排序和MST遍历边用;
另外一份用邻接表表示有提高计算环时候的处理速度,数据结构确定了那么很容易利用DFS回溯,在DFS回溯的
过程中判断环以及是否有和目标边权值相等的边,判断环没有用并查集而是直接在DFS中判断
6085976    bobten2008    1679    Accepted    256K    0MS    C++    2201B    2009-11-03 20:42:08
*/

#include <iostream>
#include <algorithm>
#define MAX_E 5010
#define MAX_N 105
using namespace std;

//MST算法中用来表示当前节点是否被访问过
bool v[MAX_N + 1];
//存储所有边
struct edge
{
    int from, to, w;
}edges[MAX_E + 1];
//节点数以及边数
int noden, edgen;
//边的邻接表存储
struct head
{
    int from, to, w;
    head *next;
}*heads[MAX_N + 1];
//对边按照权值升序排列的比较函数
bool compare(const edge &e1, const edge &e2)
{
    return e1.w <= e2.w;
}
//初始化
void init()
{
    int i;
    for(i = 1; i <= noden; i++)
    {
        heads[i] = NULL;        
        v[i] = false;
    }
}
//往邻接表中插入边
void insertEdge(int from, int to, int w)
{
    head *temp = new head();
    temp->from = from; temp->to = to; temp->w = w;
    temp->next = heads[from];
    heads[from] = temp;
}
//dfs算法判断换需要的相关参数,dfsDest表示目标结点,dfsW表示目标边的权值
int dfsDest, dfsW;
//ununique用来表示MST是否唯一
bool ununique;
//dfs算法中用来比较当前节点是否被访问过
bool dfsv[MAX_N + 1];
//返回值为true表示从curNode往后可以遍历到dfsDest,即构成一条环
bool dfsCheckCycle(int curNode)
{
    //减枝,如果已经发现MST不唯一则退出
    if(ununique) return true;
    //到达目标节点,即发现环
    if(curNode == dfsDest) return true;
    bool returnval = false;
    //当前节点如果没有被访问过
    if(!dfsv[curNode])
    {
        //访问当前节点
        dfsv[curNode] = true;
        //访问当前节点的所有邻居
        head *temp = heads[curNode];
        while(temp)
        {
            bool cur;
            //如果从邻居temp->to可以形成环,且这条边的权值等于dfsW,则预示着MST不唯一
            if((cur = dfsCheckCycle(temp->to)) && temp->w == dfsW)
            {
                ununique = true;
                return true;
            }
            temp = temp->next;
            returnval |= cur;
        }
        dfsv[curNode] = false;
        return returnval;
    }
    else return false;
}
//MST算法
int getMST()
{
    int countv = 0, pos = 0, total = 0;
    while(countv < noden && pos < edgen)
    {
        int from = edges[pos].from, to = edges[pos].to, w = edges[pos].w;
        //cycle
        if(v[from] && v[to])
        {
            memset(dfsv, 0, sizeof(dfsv));
            dfsDest = to;
            dfsW = w;
            ununique = false;
            //寻找是否存在环中权值与w相同的其他边
            bool haveCircle = dfsCheckCycle(from);

            if(ununique) return -1;
            if(haveCircle) { //有环布插入边

                pos++;
                continue;

            }
        }
        //无欢插入边
        v[from] = v[to] = true;
        total += w;
        insertEdge(from, to, w);
        insertEdge(to, from, w);
        pos++;
    }
    return total;
}
int main()
{
    int caseNum, i;
    scanf("%d", &caseNum);
    while(caseNum--)
    {
        scanf("%d%d", &noden, &edgen);
        init();
        int from, to, w;
        for(i = 0; i < edgen; i++)
        {
            scanf("%d%d%d", &from, &to, &w);
            edges[i].from = from;
            edges[i].to = to;
            edges[i].w = w;
            //insertEdge(from, to, w); insertEdge(to, from, w);
        }
        sort(edges, edges + edgen, compare);
        int res = getMST();
        if(res == -1) printf("Not Unique!/n");
        else printf("%d/n", res);
    }
    return 0;
}

你可能感兴趣的:(数据结构,c,算法,struct,null,存储)