POJ 1679 判最小生成树的不唯一性 或 利用次小生成树求解
题目大意:
给定一个无向图,寻找它的最小生成树,如果仅有一种最小生成树,输出所有边的和,否则输出unique!
根据kruscal原理来说,每次不断取尽可能小的边不断添加入最小生成树中,那么可知如果所有边的长度都不相同,那么kruscal取得过程必然只有一种情况,由小到大
所以要是存在多种情况的最小生成树,那么必然是存在相同的边
初始将所有相同的边进行标记,生成第一次最小生成树后,不断去除其中带标记的边,然后再计算最小生成树,判断能否得到同样的答案,如果可以,说明不止一种情况
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 105
int fa[N] , same[N] , first[N] , k;
int rec[N] , amo;//rec[]记录MST中含有相同长度边的位置,amo记录其数量
struct Edge{
int x,y,d,next,flag;
bool same;
bool operator<(const Edge &m) const{
return d<m.d;
}
}e[N*N]; int find_head(int x)
{
while(fa[x]!=x) x=fa[x];
return x;
} bool Union(int x,int y)
{
int fa_x = find_head(x);
int fa_y = find_head(y);
fa[fa_x] = fa_y;
return fa_x == fa_y;
} void add_edge(int x, int y , int d)
{
e[k].x=x , e[k].y=y , e[k].d=d , e[k].flag= , e[k].next=first[x];
e[k].same = false;
first[x] = k++;
} int cal_MST(int n , int flag)
{
int ans = , cnt=;
for(int i= ; i<=n ; i++) fa[i]=i;
for(int i= ; i<k ; i++){
if(e[i].flag==){
if(!Union(e[i].x , e[i].y)){
ans+=e[i].d;
if(e[i].same && flag){
rec[amo++] = i;
}
cnt++;
if(cnt == n-) break;
}
}
}
return ans;
} int main()
{
int T;
scanf("%d" , &T);
while(T--)
{
int n , m , x , y , d;
scanf("%d%d" , &n , &m);
k=;
memset(first , - , sizeof(first));
for(int i= ; i<m ; i++){
scanf("%d%d%d" , &x , &y , &d);
add_edge(x , y , d);
} sort(e , e+k);
//对存在相同边的边进行标记
for(int i= ; i<k ; i++)
if(e[i].d == e[i-].d) e[i].same=e[i-].same=true;
amo = ;
int ans = cal_MST(n , );
bool is_unique = true;
for(int i= ; i<amo ; i++){
e[rec[i]].flag = ;
int t=cal_MST(n , );
if(t == ans){
is_unique=false;
break;
}
e[rec[i]].flag = ;
}
if(is_unique) printf("%d\n" , ans);
else puts("Not Unique!");
}
return ;
}
上面那个明显复杂度比较高
我们可以求解出次小生成树的值与最小生成树的值进行比较判断是否唯一
先求出最小生成树,用二维数组mx[][]记录最小生成树上两个点之间路径上最长边的长度
然后找到每一条不属于最小生成树的边u,v ,这样可以与原最小生成树中u->v的路径形成一个环,那么最后需要在环中删去一条最长边,那么只要不断得到这个差值的最小值
用最小生成树的值减去他就可以了
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define N 105
const int INF = 0x3f3f3f3f;
int mx[N][N] , w[N][N];
int n , m;
int d[N] , connect[N];
bool vis[N][N] , in[N]; int prim()
{
int ret = ;
memset(vis , , sizeof(vis));
memset(connect , , sizeof(connect));
memset(in , , sizeof(in));
memset(mx , , sizeof(mx));
d[] = INF , in[] = true;
for(int i= ; i<=n ; i++)
if(w[][i]>=){
d[i] = w[][i];
connect[i] = ;
}
else d[i] = INF; for(int i= ; i<n ; i++){
int minn = INF , index = ;
for(int j= ; j<=n ; j++){
if(in[j]) continue;
if(d[j]<minn) minn=d[j] , index=j;
}
int u = connect[index];
d[index] = INF , vis[index][u] = vis[u][index] = true;
mx[index][u] = mx[u][index] = minn , in[index] = true , ret+=minn;
for(int j= ; j<=n ; j++){
if(in[j] || w[index][j]<) continue;
if(w[index][j]<d[j]) d[j] = w[index][j] , connect[j] = index;
}
for(int j= ; j<=n ; j++){
if(!in[j]) continue;
mx[j][index] = mx[index][j] = max(mx[index][j] , max(mx[index][u] , minn));
}
}
return ret;
} int sec_mst(int mst)
{
int del = INF;
for(int i= ; i<=n ; i++){
for(int j=i+ ; j<=n ; j++){
if(!vis[i][j] && w[i][j]>=){
del = min(del , mx[i][j]-w[i][j]);
}
}
}
return mst-del;
} int main()
{
// freopen("in.txt" , "r" , stdin);
int T;
scanf("%d" , &T);
while(T--)
{
scanf("%d%d" , &n , &m);
memset(w , - , sizeof(w));
int u , v , wei;
while(m--){
scanf("%d%d%d" , &u , &v , &wei);
w[u][v] = w[v][u] = wei;
}
int ret = prim();
int sec = sec_mst(ret);
if(ret == sec) puts("Not Unique!");
else printf("%d\n" , ret);
}
return ;
}
POJ 1679 判最小生成树的不唯一性 或 利用次小生成树求解的更多相关文章
- poj 1679 判断最小生成树是否唯一
/* 只需判断等效边和必选边的个数和n-1的关系即可 */ #include<stdio.h> #include<stdlib.h> #define N 110 struct ...
- 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 (最小生成树)
The Unique MST 题目链接: http://acm.hust.edu.cn/vjudge/contest/124434#problem/J Description Given a conn ...
- POJ 1679 The Unique MST(次小生成树)
题意:求解最小生成树的权值是否唯一,即要我们求次小生成树的权值两种方法求最小生成树,一种用prim算法, 一种用kruskal算法 一:用prim算法 对于给定的图,我们可以证明,次小生成树可以由最小 ...
- 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)
洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...
- 洛谷P4180 [BJWC2010]次小生成树(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)
洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...
- POJ 1679 The Unique 次最小生成树 MST
http://poj.org/problem?id=1679 题目大意: 给你一些点,判断MST(最小生成树)是否唯一. 思路: 以前做过这题,不过写的是O(n^3)的,今天学了一招O(n^2)的,哈 ...
- (poj)1679 The Unique MST 求最小生成树是否唯一 (求次小生成树与最小生成树是否一样)
Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definit ...
- POJ 1679 The Unique MST (次小生成树 判断最小生成树是否唯一)
题目链接 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. De ...
随机推荐
- thinkphp3.2 + soap
服务器配置 扩展libxml2下载地址:http://xmlsoft.org/downloads.html 在windows下的php.ini文件里 找到这一行代码(如没有则自行添加) extensi ...
- 关于jquery获取单选框value属性值为on的问题
当取单选框的value值的时候,前提是要有value这个属性,如果没有value属性那么取出来的就会为on 取value值的常见三种方式为 $("input[name='XXX']:chec ...
- AJPFX:关于面向对象的封装
1.回顾 面向对象 -- 注重的是结果,强调的是具备功能的对象. 面向过程 -- 强调的是函数,注重的实现的过程. 函数:对功能的封装. ...
- 如何在tomcat部署项目(用ip访问)
找了好长时间的错误,server.xml中一点错误也没有,但就是访问不到,最终发现就是服务器没有开放80端口的缘故. 服务器是Windows系统 1.控制面板=>系统和安全=>Window ...
- 简洁大方的wordpress主题,不容错过的主题,附带主题源码下载
cu主题是由疯狂的大叔设计,界面简洁大方是它最大的特点之一. 手残君也比较喜爱这款主题,在使用的过程中,根据手残君的个人习惯,对其进行了优化. 标题优化 标题居中显示 增加标题div背景色 标题div ...
- struts 2.5 There is no Action mapped for namespace [/] and action name [user_find] associated with context path [/struts2_crm].
遇到了这个错误. There is no Action mapped for namespace [/] and action name [user_find] associated with con ...
- SQL优化基础 使用索引(一个小例子)
按照本文操作和体会,会对sql优化有个基本最简单的了解,其他深入还需要更多资料和实践的学习: 1. 建表: 复制代码代码如下: create table site_user ( id int IDEN ...
- 关于mapState和mapMutations和mapGetters 和mapActions辅助函数的用法及作用(四)-----mapActions
介绍mapActions辅助函数: Action提交的是Mutation,不能够直接修改state中的状态,而Mutations是可以直接修改state中状态的:Action是支持异步操作的,而Mut ...
- WebSocket 的一些简单页面推送使用
因为做通信项目的时候,需要实时获取每个分机的当前状态,发现websocket还不错,只是对浏览器的要求比较高, 针对特定用户推送消息,网上有一些 public class GetHttpSession ...
- SQL Server错误: 0 解决方案
1.已设置两种登录模式. 2.SQL Server配置管理器已配置好. 按Windows徽标键+R组合键,然后输入cmd. 再然后输入netsh winsock reset.接下来重启电脑,应该就可以 ...