poj1679 The Unique MST(判定次小生成树)
| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 23180 | Accepted: 8235 |
Description
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
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
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!
Source
对于最小生成树(能够用kruskal和prime算法求得,在这里我是用kruskal求得,假设不会请自己百度。),边的权值的和最小称为最小生成树。
而次小生成树就是除了最小生成树外的最小生成树。并且全部的次小生成树都是通过最小生成树的换边得到的。
所以难点就是怎样换边。
对于怎样换边:
1.先求出最小生成树,值为x。
2.一一枚举加入不在生成树上的边(这时候一定形成了一个环)
3.寻找环上的(最小生成树上的边)权值最大值与你所加入不在生成树上的边的权值比較,所得到的差值为min。
因为是一一枚举加入边,min有多个,求出最小的哪一个,所以次小生成树就为x+min。
昨天尽管把这道题A了,但是看到讨论区的測试数据发现自己又一个没有过,然而却AC了。然后今天起床就来研究研究。
。
。
发现我的程序是在找最大值。但是假设一个环有分支,它还会去找分支里面的最大值。于是就又优化了一下。
用的优先队列。
先附上第一次做的代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
struct node
{
int a,b,cost;
}c[10005];
int fa[105],tree[105][105],vis[10005],vis_tree[105];//vis数组是对m对数据的标记vis_tree是对最小生成树标记
int n,m,max1;
bool cmp(node x,node y)
{
if(x.cost<y.cost)
return true;
else
return false;
}
int find(int x)//寻找根
{
if(fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
void sec_tree(int a,int b)//查找生成树某条边的最大值(我在这里做的是错误的。假设形成的环有分支,也会查找)
{
vis_tree[a]=1;
if(a==b)
return ;
for(int i=1;i<=n;i++)
if(tree[a][i]&&!vis_tree[i])
{
if(max1<tree[a][i])
max1=tree[a][i];
sec_tree(i,b);
}
}
int main()
{
int ncase;
scanf("%d",&ncase);
while(ncase--)
{
memset(vis,0,sizeof(vis));
memset(tree,0,sizeof(tree));
memset(&c,0,sizeof(&c));
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=0;i<m;i++)
scanf("%d %d %d",&c[i].a,&c[i].b,&c[i].cost);
sort(c,c+m,cmp);
int sum=0;
for(int i=0;i<m;i++)//kruskal算法求最小生成树
{
int x=find(c[i].a);
int y=find(c[i].b);
if(x!=y)
{
fa[x]=y,sum+=c[i].cost;
tree[x][y]=tree[y][x]=c[i].cost;
vis[i]=1;
}
}
int flag=0;
for(int i=0;i<m;i++)
{
if(!vis[i])//不在生成树中的边和形成的环的最大值比較。假设相等,MST不唯一
{
max1=-1;
memset(vis_tree,0,sizeof(vis_tree));
sec_tree(c[i].a,c[i].b);
if(max1==c[i].cost)
{
flag=1;
break;
}
}
}
if(!flag)
printf("%d\n",sum);
else
printf("Not Unique!\n");
}
}
这是优化后的代码。凝视和上面一样。就一个地方不同:
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
struct node1
{
int a,b,cost;
friend bool operator<(node1 x,node1 y )
{
return x.cost<y.cost;
}
};
priority_queue<node1>s;
struct node
{
int a,b,cost;
}c[10005];
int fa[105],tree[105][105],vis[10005],vis_tree[105];
int n,m,max1,flag1;
bool cmp1(node x,node y)
{
if(x.cost<y.cost)
return true;
else
return false;
}
int find(int x)
{
if(fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
void sec_tree(int a,int b)
{
node1 temp;
vis_tree[a]=1;
if(a==b)//假设找到a=b,标记一下
{
flag1=1;
}
for(int i=1;i<=n;i++)
if(tree[a][i]&&!vis_tree[i])
{
temp.a=a,temp.b=i,temp.cost=tree[a][i];
s.push(temp);
if(!flag1)//就是在这里和上面不同,假设找不到a=b,那么就把曾经的恢复
s.pop(),vis_tree[i]=0,sec_tree(i,b);
}
}
int main()
{
int ncase;
scanf("%d",&ncase);
while(ncase--)
{
memset(vis,0,sizeof(vis));
memset(tree,0,sizeof(tree));
memset(&c,0,sizeof(&c));
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=0;i<m;i++)
scanf("%d %d %d",&c[i].a,&c[i].b,&c[i].cost);
sort(c,c+m,cmp1);
int sum=0;
for(int i=0;i<m;i++)
{
int x=find(c[i].a);
int y=find(c[i].b);
if(x!=y)
{
fa[x]=y,sum+=c[i].cost;
tree[x][y]=tree[y][x]=c[i].cost;
vis[i]=1;
}
}
int flag=0;
for(int i=0;i<m;i++)
{
if(!vis[i])
{
int flag1=0;
while(!s.empty())
s.pop();
memset(vis_tree,0,sizeof(vis_tree));
sec_tree(c[i].a,c[i].b);
node1 temp;
temp=s.top();
if(temp.cost==c[i].cost)
{
flag=1;
break;
}
}
}
if(!flag)
printf("%d\n",sum);
else
printf("Not Unique!\n");
}
}
poj1679 The Unique MST(判定次小生成树)的更多相关文章
- POJ-1679 The Unique MST(次小生成树、判断最小生成树是否唯一)
http://poj.org/problem?id=1679 Description Given a connected undirected graph, tell if its minimum s ...
- POJ1679 The Unique MST 【次小生成树】
The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 20421 Accepted: 7183 D ...
- POJ1679 The Unique MST【次小生成树】
题意: 判断最小生成树是否唯一. 思路: 首先求出最小生成树,记录现在这个最小生成树上所有的边,然后通过取消其中一条边,找到这两点上其他的边形成一棵新的生成树,求其权值,通过枚举所有可能,通过这些权值 ...
- POJ1679 The Unique MST(次小生成树)
可以依次枚举MST上的各条边并删去再求最小生成树,如果结果和第一次求的一样,那就是最小生成树不唯一. 用prim算法,时间复杂度O(n^3). #include<cstdio> #incl ...
- The Unique MST(次小生成树)
Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 22335 Accepted: 7922 Description Give ...
- POJ1679The Unique MST(次小生成树)
The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 25203 Accepted: 8995 D ...
- poj 1679 The Unique MST【次小生成树】
The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 24034 Accepted: 8535 D ...
- POJ 1679:The Unique MST(次小生成树&&Kruskal)
The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 19941 Accepted: 6999 D ...
- poj 1679 The Unique MST 【次小生成树】【模板】
题目:poj 1679 The Unique MST 题意:给你一颗树,让你求最小生成树和次小生成树值是否相等. 分析:这个题目关键在于求解次小生成树. 方法是,依次枚举不在最小生成树上的边,然后加入 ...
- POJ 1679 The Unique MST (次小生成树)题解
题意:构成MST是否唯一 思路: 问最小生成树是否唯一.我们可以先用Prim找到一棵最小生成树,然后保存好MST中任意两个点i到j的这条路径中的最大边的权值Max[i][j],如果我们能找到一条边满足 ...
随机推荐
- java正則表達式总结
近期用到的正則表達式 因为近期在做一个android的新闻client.多次用到了正則表達式.因此总结下. 1.使用正則表達式获取Rss资源内的文章内容的图片url 由于在每条新闻浏览的listVie ...
- BZOJ 3210 花神的浇花集会 计算几何- -?
题目大意:给定平面上的n个点,求一个点到这n个点的切比雪夫距离之和最小 与3170不同的是这次选择的点无需是n个点中的一个 首先将每一个点(x,y)变为(x+y,x-y) 这样新点之间的曼哈顿距离的一 ...
- Activity 之间 传递 List 封装的对象或者对象
项目中遇到 从也个页面向还有一个页面跳转传递一个List 封装的对象 .按网上查的资料 须要把 对象 实现 Serializable接口. 写了一下.可是跳转直接崩溃.一直看错误之日找不到原因后来自习 ...
- LinkCutTree详解
LCT详解 没有比这再详细的了, 相信我
- javafx ComboBox Event and change cell color
public class EffectTest extends Application { public static void main(String[] args) { launch(args); ...
- c# array arraylist 泛型list
1 array 数组 是存储相同类型元素的固定大小的数据的顺序集合.在内存中是连续存储的,所以索引速度非常快,而且赋值和修改元素也非常简单. //定义字符串数组 大小为3 string[] str1 ...
- ES6--基础语法(一)
一.支持环境:node.js完全支持,标准浏览器完全支持.二.测试环境: chrome下需要在script标签的最先开始的地方需要添加"use strict". firefox下需 ...
- django shell 操作
插件:django-extensions django-extensions==1.9.8 pip3 install django-extensions 1.数据库shell 命令(项目目录下) p ...
- SpringMVC框架中的异常解析器-ExceptionHandler和HandlerExceptionResolver
SpringMVC框架中,处理异常还是挺方便的,提供了一个异常解析器. 处理局部异常 @Controller public class AccessController { /** * 处理这个Con ...
- [Express] Upload Files with Express
In this lesson we create a new Express web server app for handling file uploads and persisting them ...