UVa 10600 - ACM Contest and Blackout(最小生成树)

来源:互联网 发布:淘宝灵异事件 编辑:程序博客网 时间:2024/05/22 07:09

赤裸裸的最小生成树。


第一次生成树得出最优解,并记录用到了哪些边。

然后枚举,用op标记删除其中一条边,得到最小生成树。其中消费最小的即为所求。


#include <iostream>#include <cstdio>#include <vector>#include <cstdlib>#include <cstring>#include <algorithm>using namespace std;int p[111], n, m;int find(int x){    return x==p[x]?x:p[x]=find(p[x]);}struct Edge{    int x, y, c, op;    Edge(int x=0, int y=0, int c=0, int op=0):x(x), y(y), c(c), op(op) {}    bool operator < (const Edge a)const    {        return c<a.c;    }};vector<Edge> edge;void init(){    for(int i=1; i<=n; i++)        p[i]=i;}int solve(){    int i=0, cost=0, cnt=0;    while(cnt<n-1 && i<m)    {        if(edge[i].op)        {            i++;            continue ;        }        int x=find(edge[i].x), y=find(edge[i].y);        if(x!=y)        {            p[x]=y;            cost+=edge[i].c;            cnt++;        }        i++;    }    if(cnt!=n-1)return 1e9;    return cost;}int main(){    int t;    scanf("%d", &t);    while(t--)    {        scanf("%d%d", &n, &m);        init();        edge.clear();        for(int i=0; i<m; i++)        {            int a, b, c;            scanf("%d%d%d", &a, &b, &c);            edge.push_back(Edge(a, b, c, 0));        }        sort(edge.begin(), edge.end());        int cnt=0, i=0, cost=0;        vector<int> v;        v.clear();        while(cnt<n-1)        {            int x=find(edge[i].x), y=find(edge[i].y);            if(x!=y)            {                p[x]=y;                cost+=edge[i].c;                v.push_back(i);                cnt++;            }            i++;        }        cout<<cost<<" ";        int res=1e9;        for(int i=0; i<v.size(); i++)        {            init();            edge[v[i]].op=1;            res=min(res, solve());            edge[v[i]].op=0;        }        cout<<res<<endl;    }    return 0;}


0 0
原创粉丝点击