POJ 1679 The Unique 次最小生成树 MST
http://poj.org/problem?id=1679
题目大意:
给你一些点,判断MST(最小生成树)是否唯一。
思路:
以前做过这题,不过写的是O(n^3)的,今天学了一招O(n^2)的,哈哈~
方法一:
首先先建立MST,然后把这个MST的边一个个尝试不使用,构建另外一颗MST,然后判断权值是否相等。
这样复杂度需要O(n^3)。。
方法二:
还可以用次最小生成树的方法解决:如果最小生成树不唯一,那么次小生成树的权值和最小生成树相同。
我们可以枚举要加入哪一条新边。在最小生成树上加一条边u-v之后,图上会出现一条回路。因此删除的边必须在最小生成树u到v的路径上,而且是这条路径上的最长边。而次最小生成树一定能由最小生成树加一条再删除一条边得到。只需我们求出没对结点u和v在最小生成树中唯一路径的最大边权dp[i][j],剩下的只需O(m)时间,枚举所有的m-n+1条边进行交换,每次花O(1)时间求出新生成树的权值。总时间复杂度为O(n^2)
方法一:
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=101;
int fa[MAXN]; struct point
{
int x,y;
int len;
}data[MAXN*MAXN],pre[MAXN*MAXN]; //pre 记录等一下用到了哪些条边 bool operator < (const point &a ,const point &b) //sort 重载比较函数
{
return a.len<b.len;
} void UFinit(int n) //并查集初始化
{
for(int i=1;i<=n;i++)
fa[i]=i;
} int find(int cur) //带路径压缩的并查集查询函数,简洁而优雅~
{
return fa[cur]==cur? cur : fa[cur]=find(fa[cur]);
} int kruskal(int n,int m,int &prelen)
{
UFinit(n);
int ans=0;
for(int i=0;i<m;i++)
{
int rootx=find(data[i].x);
int rooty=find(data[i].y);
if(rootx!=rooty)
{
fa[rootx]=rooty;
ans+=data[i].len;
pre[prelen++]=data[i]; }
} return ans;
} int kruskal2(int n,int m,int nox,int noy)//nox noy 代表直接连接这两个点之间的边不选
{
UFinit(n); int ans=0;
for(int i=0;i<m;i++)
{
if(data[i].x==nox && data[i].y==noy)
continue; int rootx=find(data[i].x);
int rooty=find(data[i].y);
if(rootx!=rooty)
{
fa[rootx]=rooty;
ans+=data[i].len;
}
} return ans; }
int main()
{ int T;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
scanf("%d%d%d",&data[i].x,&data[i].y,&data[i].len); int prelen=0; //pre数组的长度
sort(data,data+m); //kruskal 前面的工作 int ans=kruskal(n,m,prelen); //正常版本的kruskal bool unique=true; for(int i=0;i<prelen;i++)
{
int res=kruskal2(n,m,pre[i].x,pre[i].y);//带去除边的kruskal int cnt=0;
for(int j=1;j<=n;j++)
if(fa[i]==i)
cnt++; if(cnt!=0) //这个很重要!没有就WA,因为可能剩下的不连通,但是恰好res==ans
continue; if(res==ans) //如果还有一棵生成树和第一次所求的权值一样,说明最小生成树不唯一
{
unique=false;
break;
}
} if(unique)
printf("%d\n",ans);
else
printf("Not Unique!\n");
}
return 0;
}
方法二:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=100+10;
int n,m,head[MAXN],len,fa[MAXN],nodes[MAXN],n_len;
int dp[MAXN][MAXN];
bool vis[MAXN];
int find(int cur) //带路径压缩的并查集查询函数,简洁而优雅~
{
return fa[cur]==cur? cur : fa[cur]=find(fa[cur]);
} struct edge //MST邻接表
{
int to,next;
double val;
}e[MAXN*MAXN]; void add(int from,int to,double val)
{
e[len].to=to;
e[len].val=val;
e[len].next=head[from];
head[from]=len++;
}
struct point
{
int x,y;
int len;
bool operator < (const point &b) const//sort 重载比较函数
{
return len<b.len;
} }data[MAXN*MAXN]; void dfs(int cur,int fa,int dis)
{
for(int i=0;i<n_len;i++)
{
int x=nodes[i];
dp[cur][x]=dp[x][cur]=max(dp[x][fa],dis);
} nodes[n_len++]=cur; for(int i=head[cur];i!=-1;i=e[i].next)
{
int id=e[i].to;
if(id != fa)
dfs(id,cur,e[i].val);
}
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(head,-1,sizeof(head));
len=0;
memset(vis,0,sizeof(vis));
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
scanf("%d%d%d",&data[i].x,&data[i].y,&data[i].len); for(int i=1;i<=n;i++)
fa[i]=i; //kruskal
sort(data,data+m);
int mstlen=0;
for(int i=0;i<m;i++)
{
int x=data[i].x,y=data[i].y;
int root_x=find(x),root_y=find(y);
if(root_x!=root_y)
{
mstlen+=data[i].len;
fa[root_x]=root_y;
add(x,y,data[i].len); //kruskal中顺便建立MST的邻接表
add(y,x,data[i].len);
vis[i]=true;
}
}
n_len=0;
memset(dp,0,sizeof(dp));
dfs(1,-1,0);
int mstlen2=9999999;
for(int i=0;i<m;i++)
{
if(vis[i]) continue;
int x=data[i].x,y=data[i].y,dis=data[i].len;
mstlen2=min(mstlen2,mstlen - dp[x][y] + dis);
}
// printf("%d\n",mstlen2);
if(mstlen == mstlen2)
puts("Not Unique!");
else
printf("%d\n",mstlen);
}
return 0;
}
POJ 1679 The Unique 次最小生成树 MST的更多相关文章
- poj 1679 The Unique MST 【次小生成树】【模板】
题目:poj 1679 The Unique MST 题意:给你一颗树,让你求最小生成树和次小生成树值是否相等. 分析:这个题目关键在于求解次小生成树. 方法是,依次枚举不在最小生成树上的边,然后加入 ...
- poj 1679 The Unique MST(唯一的最小生成树)
http://poj.org/problem?id=1679 The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submis ...
- poj 1679 The Unique MST (判定最小生成树是否唯一)
题目链接:http://poj.org/problem?id=1679 The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total S ...
- POJ 1679 The Unique MST 【最小生成树/次小生成树模板】
The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 22668 Accepted: 8038 D ...
- poj 1679 The Unique MST
题目连接 http://poj.org/problem?id=1679 The Unique MST Description Given a connected undirected graph, t ...
- POJ 1679 The Unique MST (次小生成树kruskal算法)
The Unique MST 时间限制: 10 Sec 内存限制: 128 MB提交: 25 解决: 10[提交][状态][讨论版] 题目描述 Given a connected undirect ...
- POJ 1679 The Unique MST(判断最小生成树是否唯一)
题目链接: http://poj.org/problem?id=1679 Description Given a connected undirected graph, tell if its min ...
- 【POJ 1679 The Unique MST】最小生成树
无向连通图(无重边),判断最小生成树是否唯一,若唯一求边权和. 分析生成树的生成过程,只有一个圈内出现权值相同的边才会出现权值和相等但“异构”的生成树.(并不一定是最小生成树) 分析贪心策略求最小生成 ...
- POJ 1679 The Unique MST 【判断最小生成树是否唯一】
Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Defini ...
随机推荐
- android 图片特效处理之图片叠加
这篇将讲到图片特效处理的图片叠加效果.跟前面一样是对像素点进行处理,可参照前面的android图像处理系列之七--图片涂鸦,水印-图片叠加和android图像处理系列之六--给图片添加边框(下)-图片 ...
- Linux下VsFTP和ProFTP用户管理高级技巧 之一
Linux下VsFTP和ProFTP用户管理高级技巧 FTP服务时互联网上比较古老的一种应用,至今Interner应用面非常广泛,但令管理员头痛不已的是其用户管理,既多且杂,如何解决这一问 ...
- Android studio文件名颜色分别表示含义
这其实是主要和版本控制工具有关,含义如下: 绿色,已经加入控制暂未提交红色,未加入版本控制蓝色,加入,已提交,有改动白色,加入,已提交,无改动 灰色:版本控制已忽略文件
- 小的时候.by小雷
小的时候,总是有很多想法. 想去做,却做不成. 因为,自己小,被父母约束着,被学校圈着,被老师教育着. 想买个小霸王游戏机,没钱.在父辈的眼中,"游戏" ,游戏室,电脑游戏 ...
- Java 学习(15):Java 数据结构
Java 数据结构 Java工具包提供了强大的数据结构.在Java中的数据结构主要包括以下几种接口和类: 枚举(Enumeration) 位集合(BitSet) 向量(Vector) 栈(Stack) ...
- cocos2dx——lua自己主动和手动绑定
[自己主动绑定] 參考:http://my.oschina.net/skyhacker2/blog/298397 主要是通过引擎自带的tools/tolua,主要过程例如以下: 1.编写好要导出的c+ ...
- 10款jQuery/CSS3动画应用 超有用
http://www.html5tricks.com/10-jquery-css3-animation.html
- 类名引用static变量好处
不仅强调了变量static的结构,而且在有些情况下他还为编译器进行优化提供了更好的机会.
- 34.node.js之Url & QueryString模块
转自:https://i.cnblogs.com/posts?categoryid=1132005&page=6//引用 var url = require("url"); ...
- 《四》JAVA 字符输入输出流
那么这篇博客我们讲的是字节输入输出流:Reader.Writer(下图红色长方形框内),红色椭圆框内是其典型实现(FileReader.FileWriter) ①.为什么要使用字符流? 因为使用字节流 ...