[poj 1679] The Unique MST---(翻译:次小生成树)

来源:互联网 发布:三维热传导模拟软件 编辑:程序博客网 时间:2024/06/05 05:17

Description

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!

题目大意:给定图,判断它的最小生成树是否唯一。如果唯一的话输出最小生成树的权值和,否则输出Not Unique!

输入:
T(几组数据)
N(节点数) M(边数)
from to w( 起点,终点,权值 )

分析

赤裸裸的次小生成树,当次小生成树的权值与最小生成树的权值相等时,则方案不唯一

代码

#include <cstdio>#include <cstdlib>#include <cstring>#include <vector>#include <algorithm>#define open(s) freopen(s".in","r",stdin); freopen(s".out","w",stdout);#define close fclose(stdin); fclose(stdout); using namespace std;struct Edge1{    int from;    int to;    int w;    bool f;    bool operator < (const Edge1 &b)    {        return w<b.w;    }};struct Edge2{    int to;    int next;    int w;    inline void clr()    {        to=next=w=0;    }};int cnt;bool F;int n,m;int head[105];int fa[105];int size[105];int dp[105][105];bool vis[105];Edge1 side[10005];Edge2 edge[5000];vector<int>setx;inline int read(){    int k=1;    int sum=0;    char c=getchar();    for(;'0'>c || c>'9' ;c=getchar())        if(c=='-') k=-1;    for(;'0'<=c && c<='9';c=getchar())        sum=sum*10+c-'0';    return sum*k;}inline void write(int x){    if(x<0) { putchar('-'); x*=-1; }    if(x>9) write(x/10);    putchar(x%10+'0');}inline void add(int x,int y,int z)  //加边{    ++cnt;    edge[cnt].to=y;    edge[cnt].w=z;    edge[cnt].next=head[x];    head[x]=cnt;}inline int find(int x) //并查集{    return fa[x]=(fa[x]==x?x:find(fa[x]));}inline bool join(int x,int y)//并查集{    int x1=find(x),y1=find(y);    if(x1==y1) return 0;    if(size[x1]>size[y1])    {        size[x1]+=size[y1];        fa[y1]=x1;    }else    {        size[y1]+=size[x1];        fa[x1]=y1;    }    return 1;}inline int kruskal() //最小生成树{    for(int i=1;i<=n;++i)    {        fa[i]=i;        size[i]=1;    }    sort(side+1,side+m+1);    int t=n-1;    int sum=0;    for(int i=1;i<=m && t;++i)    if(join(side[i].from,side[i].to))    {        --t;        sum+=side[i].w;        add(side[i].from,side[i].to,side[i].w);        add(side[i].to,side[i].from,side[i].w);        side[i].f=1;    }    if(t) sum=-1;    return sum;}inline int max(int x,int y) //忽略{    return x>y?x:y;}inline int min(int x,int y)//忽略{    return x<y?x:y;}inline void dfs(int now) //求任意两点的最小瓶颈路{    vis[now]=1; setx.push_back(now);    for(int i=head[now];i;i=edge[i].next)    if(!vis[edge[i].to])    {        int y=edge[i].to;        for(int j=setx.size()-1;j>=0;--j)            dp[y][setx[j]]=dp[setx[j]][y]=max(dp[setx[j]][now],edge[i].w);        dfs(y);    }}inline void solve(){    n=read(); m=read();    F=1;    for(int i=1;i<=m;++i)    {        side[i].from=read();        side[i].to=read();        side[i].w=read();        side[i].f=0;    }    memset(head,0,sizeof(head));    for(;cnt;--cnt)        edge[cnt].clr();    int ans=kruskal(); //最小生成树权值和    if(ans<0) F=0;    if(F)    {        setx.clear(); //初始化        memset(dp,0,sizeof(dp));        memset(vis,0,sizeof(vis));        dfs(1); //预处理        int mi=0x3f3f3f3f;        for(int i=1;i<=m;++i)        if(!side[i].f)        {            mi=min(mi,ans+side[i].w-dp[side[i].from][side[i].to]); //次小生成树权值和            if(mi==ans){ F=0; break; }        }    }    if(F) write(ans); else printf("Not Unique!");    putchar('\n');}int main(){    open("1679");    for(int T=read();T;--T)        solve();    close;    return 0;}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 30万美金美金中国被扣怎么办 电脑使用迅雷变的很卡怎么办 优盘拷贝过程中失去优盘路径怎么办 用百度云上传视频文件太慢了怎么办 网易云音乐云盘电脑上传很慢怎么办 路由器的宽带账号密码忘记了怎么办 蚂蚁邦路由器管理密码忘记了怎么办 红米2a刷机失败怎么办 小米手机开机图案锁忘记了怎么办 小米6进水无限闪屏开机重启怎么办 红米手机一直卡在开机画面怎么办 红米4卡在开机画面怎么办 红米手机一直在开机画面怎么办 红米手机一直跳开机画面怎么办 红米note3锁屏密码忘记怎么办 红米手机忘记锁屏密码怎么办 红米4锁屏密码忘了怎么办 红米note忘记锁屏密码怎么办 红米note2锁屏密码忘了怎么办 机打发票抬头名字少写一个字怎么办 卷式发票名字写错了怎么办 发票丢失了销售方不给补手续怎么办 总是把单词归不成句孑怎么办 白色踏板摩托车把漆刮了怎么办 苹果手机用流量缓冲很难怎么办 谷歌浏览器安卓手机版打不开怎么办 怀孕四个月检查高型半氨酸高怎么办 猎豹cs9怎么打不开车门怎么办 孩子在学校被老师冤枉打板子怎么办 么司福利体检暗地查乙肝怎么办 上体育课时被老师罚了腿疼怎么办 义务兵学技术不好班长打他怎么办 耳朵被打了一巴掌听不见了怎么办 耳朵被打了一巴掌后有点闷怎么办 山东省教育云平台密码戳完怎么办 被舍友知道发朋友圈说她们了怎么办 苍蝇药水进眼里了眼睛疼怎么办 三十六周了胎儿还没有入骨盆怎么办 怀孕40周了宝宝还没反应怎么办 程序员不知道自己犯法了怎么办啊 大学档案学年测评有涂改痕迹怎么办