题意:求一个无向图的最小生成树,如果有多个最优解,输出"Not Unique!"

题解:

  考虑kruskal碰到权值相同的边:

  假设点3通过边(1,3)连入当前所维护的并查集s。

  然后有一条边(下图蓝色的边)满足:

      1.长度等于(1,3)

      2.一端连到3,一端连入S。

  那么该边可以替换掉(1,3)。产生另一颗最小生成树。

关于如何判断该边一端连3,一端连入S,

用set来记录S中的点,find判断点是否在集合内。(发现kruskal可以用set写啊)

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<iostream>
#include<vector>
#include<string.h>
#include<set>
using namespace std;
const int maxn = 3e4;;set<int> s;
struct edge {
int to, from, w;
edge(int to=, int from=, int w=) :to(to), from(from), w(w) {}
}e[maxn];
bool cmp(edge a, edge b) {
return a.w < b.w;
}
int f[maxn];
int find(int x) {
return f[x] == x ? x : f[x] = find(f[x]);
}
void un(int x, int y) {
int u = find(x), v= find(y);
f[u] = v;
}
bool same(int x, int y) {
return find(x) == find(y);
}
int main() {
int t;
cin >> t;
while (t--)
{
int n, m; cin >> n >> m;
int num = ;
for (int i = ; i < m; i++) {
int x, y, z; cin >> x >> y >> z;
e[num++] = edge(x, y, z);
}
for (int i = ; i <= n; i++)f[i] = i;
sort(e, e + m,cmp);
int lastw = -, lastto = -, lastfrom = -,lastv = -;
int res=, flag=;
for (int i = ; i < m; i++) { if (same(e[i].to, e[i].from)) {
if (e[i].w == lastw) {
if (e[i].to == lastv && (s.find(e[i].from) != s.end())) { flag = ; break; }
if (e[i].from == lastv && (s.find(e[i].to) != s.end())) { flag = ; break; }
}
continue;
}
un(e[i].to, e[i].from);
        res += e[i].w;
if (s.find(e[i].to) == s.end()) lastv = e[i].to;
else lastv = e[i].from;
s.insert(e[i].to);
s.insert(e[i].from);
}
if (flag)cout << "Not Unique!";
else cout << res;
cout << endl;
}
}

队友的玄学代码(改)可以不断记录上一条被选择的边,每次选边时判断一下入度出度关系;

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<iostream>
#include<vector>
#include<string.h>
using namespace std;
const int maxn = 3e4;;
char s[maxn], str[maxn];
int len1, len2, p[maxn], ans;
struct edge {
int to, from, w;
edge(int to=, int from=, int w=) :to(to), from(from), w(w) {}
}e[maxn];
bool cmp(edge a, edge b) {
return a.w < b.w;
}
int f[maxn];
int find(int x) {
return f[x] == x ? x : f[x] = find(f[x]);
}
void un(int x, int y) {
int u = find(x), v= find(y);
f[u] = v;
}
bool same(int x, int y) {
return find(x) == find(y);
}
int main() {
int t;
cin >> t;
while (t--)
{
int n, m; cin >> n >> m;
int num = ;
for (int i = ; i < m; i++) {
int x, y, z; cin >> x >> y >> z;
e[num++] = edge(x, y, z);
e[num++] = edge(y, x, z); }
for (int i = ; i <= n; i++)f[i] = i;
sort(e, e + *m,cmp);
int lastw=-, lastto=-, lastfrom=-;
int res=, flag=;
for (int i = ; i < m*; i++) { if (same(e[i].to, e[i].from)) {
if (e[i].w == lastw) {
if ((e[i].from == lastto)&&(e[i].to!=lastfrom)) { flag = ; break; }
if ((e[i].to == lastfrom) && (e[i].from != lastto)) { flag = ; break; }
}
continue;
}
un(e[i].to, e[i].from);
res += e[i].w;
lastto = e[i].to;
lastw = e[i].w;
lastfrom = e[i].from;
}
if (flag)cout << "Not Unique!";
else cout << res;
cout << endl;
}
}

The Unique MST POJ - 1679 最小生成树判重的更多相关文章

  1. (最小生成树 次小生成树)The Unique MST -- POJ -- 1679

    链接: http://poj.org/problem?id=1679 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82831#probl ...

  2. The Unique MST POJ - 1679 (次小生成树)

    Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spann ...

  3. K - The Unique MST - poj 1679

    题目的意思已经说明了一切,次小生成树... ****************************************************************************** ...

  4. The Unique MST POJ - 1679 次小生成树prim

    求次小生成树思路: 先把最小生成树求出来  用一个Max[i][j] 数组把  i点到j 点的道路中 权值最大的那个记录下来 used数组记录该条边有没有被最小生成树使用过   把没有使用过的一条边加 ...

  5. Day5 - G - The Unique MST POJ - 1679

    Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spann ...

  6. poj 1679 The Unique MST(唯一的最小生成树)

    http://poj.org/problem?id=1679 The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submis ...

  7. POJ 1679 The Unique MST(判断最小生成树是否唯一)

    题目链接: http://poj.org/problem?id=1679 Description Given a connected undirected graph, tell if its min ...

  8. POJ1679 The Unique MST(Kruskal)(最小生成树的唯一性)

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 27141   Accepted: 9712 D ...

  9. POJ 2458 DFS+判重

    题意: 思路: 搜+判重 嗯搞定 (听说有好多人用7个for写得-.) //By SiriusRen #include <bitset> #include <cstdio>0 ...

随机推荐

  1. C++ mysql 乱码

    C++读mysql数据库中的中文显示出来的是乱码 在连接到数据库后加上这么一句 mysql_query(pMYSQL, "SET NAMES GB2312"); 或者 mysql_ ...

  2. git+gitolite+cgit+apache on Ubuntu

    git+gitolite+cgit+apache on Ubuntu Just record, do *NOT* copy-paste. git+gitolite sudo apt-get insta ...

  3. Window关闭端口的方法(445/135/137/138/139/3389等)

    为防止漏洞被利用,需要采取必要措施,关闭以上端口,以保证系统更加安全. window2003 关闭135端口的方法 要关闭此端口,只需停止DCOM接口服务即达到目的.下面是详细操作过程. 1.打开“组 ...

  4. JavaWeb学习总结(十六)Cookie保存中文内容

    Cookie的值保存中文内容,可以使用Java.net.URLDecoder进行解码. 示例: <%@page import="java.net.URLDecoder"%&g ...

  5. android新建的项目界面上没有显示怎么办?

    看log也没有说明具体情况? 一翻折腾在清单文件里加了权限就好了!!!

  6. lua_gc源码学习

    最近发现在大数据量的 lua 环境中,GC 占据了很多的 CPU .差不多是整个 CPU 时间的 20% 左右.希望着手改进.这样,必须先对 lua 的 gc 算法极其实现有一个详尽的理解.我之前读过 ...

  7. java的两种冒泡算法

    所谓的冒泡算法,就是给数组进行排序,可以根据以小到大的顺序,也可以根据以小到大的顺序,在数组的封装类java.util.Arrays通过sort方法进行按升序的排序.那不用类的话怎么进行呢? 思路一: ...

  8. ipcs命令以及oracle内存段

    今天是2014-01-06,在没过春节之前重新复习一下2013年学习的内容,关于oracle内存段在我之前写的blog中有详细操作.在此记录一下ipcs命令的用法. http://blog.csdn. ...

  9. c++ malloc与free

    今天看STL内存配置器的时候,第一级配置器就是直接用malloc.free来管理内存. 而free和malloc都只需要传入或传出一个指针就能分配和释放内存了. 编译器是如何知道,这个指针指向的空间的 ...

  10. sass - 公用方法封装

    // 设置宽高 @mixin wh($wid,$hei){ @if $wid { width: $wid; } @if $hei { height: $hei; } overflow: hidden; ...