CodeForces160D 最小生成树 + dfs
https://cn.vjudge.net/problem/26727/origin
题目大意:
给一个带权的无向图,保证没有自环和重边. 由于最小生成树不唯一,因此你需要确定每一条边是以下三种情况哪一个 1.一定在所有MST上 2.可能在某个MST上 3.一定不可能在任何MST上 输入
第一行给出n,m表示点数和边数. 数据范围见原题面 之后m行,每行给出ai,bi,wi 表示一个边的两个端点和边的权值.保证没有自环与重边. 输出
一看到这题就觉得似曾相似,仔细一看是某场比赛里卡了我三个小时的类似题,当时由于题解写的和我写的算法不一样,没有去补题。这次遇到这题偶然发现由于这题的数据开大了,之前那题的暴力算法走不通了,正好用到了我之前写了很久没找出bug的算法。
第一步显然是将所有边按权值从小到大排序,将每层权值相同的边分开来做。
第二步显然是将每层所有两点已经联通的点打上none的标记
问题在于分开必通过和可以不通过的边,上次只想到了dfs,也想到将所有已联合的点形成联通快找联通快之间必连的点,这次看了题解,发现这种联通块之间必须链接的点被称为桥,必须连接的点成为割点,寻找桥和割点都是通过tarjan算法实现的,也就是基于dfs打一个时间戳实现。
所以我们只要每一层进行见图找出所有的桥即可解决问题。
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = 1e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,tmp,K,tot,index;
int tree[maxn];
int type[maxn];
int vis[maxn];
int head[maxn];
struct Query{
int u,v,w,id;
}q[maxn];
struct Edge{
int v,next,id;
}edge[maxn * ];
bool cmp(Query a,Query b){
return a.w < b.w;
}
int find(int p){
if(p == tree[p]) return p;
return tree[p] = find(tree[p]);
}
void Union(int a,int b){
a = find(a); b = find(b);
tree[a] = b;
}
void add(int u,int v,int id){
edge[tot].v = v;
edge[tot].next = head[u];
edge[tot].id = id;
head[u] = tot++;
}
int dfs(int u,int last){
int lowu = vis[u] = ++index;
for(int i = head[u]; ~i;i = edge[i].next){
int v = edge[i].v;
if(!vis[v]){
int lowv = dfs(v,i);
lowu = min(lowu,lowv);
if(lowv > vis[u]) type[edge[i].id] = ;
}else if(vis[v] < vis[u] && i != (last ^ )){
lowu = min(lowu,vis[v]);
}
}
return lowu;
}
int main()
{
scanf("%d%d",&N,&M);
For(i,,M) scanf("%d%d%d",&q[i].u,&q[i].v,&q[i].w),q[i].id = i;
sort(q + ,q + + M,cmp);
For(i,,N) tree[i] = i;
For(i,,M){
int j = i;
while(j <= M && q[j].w == q[i].w)j++; j--;
For(k,i,j){
q[k].u = find(q[k].u);q[k].v = find(q[k].v);
int u = q[k].u; int v = q[k].v;
if(u == v){
type[q[k].id] = ;
continue;
}
type[q[k].id] = ;
vis[u] = vis[v] = ;
head[u] = head[v] = -;
}
index = tot = ;
For(k,i,j){
if(q[k].u != q[k].v){
add(q[k].u,q[k].v,q[k].id);
add(q[k].v,q[k].u,q[k].id);
}
}
For(k,i,j) if(!vis[q[k].u]) dfs(q[k].u,-);
For(k,i,j) Union(q[k].u,q[k].v);
i = j;
}
For(i,,M){
if(!type[i]) puts("none");
else if(type[i] == )puts("any");
else puts("at least one");
}
#ifdef VSCode
system("pause");
#endif
return ;
}
CodeForces160D 最小生成树 + dfs的更多相关文章
- HDU 5723 Abandoned country (最小生成树 + dfs)
Abandoned country 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5723 Description An abandoned coun ...
- HDU 5723 Abandoned country (最小生成树+dfs)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5723 n个村庄m条双向路,从中要选一些路重建使得村庄直接或间接相连且花费最少,这个问题就是很明显的求最 ...
- hdu4126(最小生成树+dfs)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4126 题意:给出一幅3000个点的图,有10000次操作: 求将某条边的权值变大后的最小生成树,最后输 ...
- HDU 2489 Minimal Ratio Tree 最小生成树+DFS
Minimal Ratio Tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- 【BZOJ3551】[ONTAK2010]Peaks加强版 最小生成树+DFS序+主席树
[BZOJ3545][ONTAK2010]Peaks Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困 ...
- BZOJ1016:[JSOI2008]最小生成树计数(最小生成树,DFS)
Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的 ...
- $bzoj1016-JSOI2008$ 最小生成树计数 最小生成树 $dfs/matrix-tree$定理
题面描述 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的).由于不同的 ...
- HDU 4081 Peach Blossom Spring (最小生成树+dfs)
题意:给定一个 n 个点和相应的权值,要求你用 n-1 条边连接起来,其中一条边是魔法边,不用任何费用,其他的边是长度,求该魔法边的两端的权值与其他边费用的尽量大. 析:先求出最小生成树,然后再枚举每 ...
- cf Inverse the Problem (最小生成树+DFS)
题意: N个点.N行N列d[i][j]. d[i][j]:结点i到结点j的距离. 问这N个点是否可能是一棵树.是输出YES,否则输出NO. 思路: 假设这个完全图是由一棵树得来的,则我们对这个完全图求 ...
随机推荐
- 【数学建模】day01-线性规划问题
线性规划问题是在一组线性约束条件下,求线性目标函数最大/最小值的问题.这些约束条件有不等式约束.等式约束以及边界约束,这和中学讲的线性规划无异. 此类问题的MATLAB标准形式为: 其中,max问 ...
- YUV格式与RGB格式
YUV420介绍: YUV420格式是指,每个像素都保留一个Y(亮度)分量,而在水平方向上,不是每行都取U和V分量,而是一行只取U分量,则其接着一行就只取V分量,以此重复(即4:2:0, 4:0:2, ...
- POJ 2245 Addition Chains(算竞进阶习题)
迭代加深dfs 每次控制序列的长度,依次加深搜索 有几个剪枝: 优化搜索顺序,从大往下枚举i, j这样能够让序列中的数尽快逼近n 对于不同i,j和可能是相等的,在枚举的时候用过的数肯定不会再被填上所以 ...
- 【BZOJ1419】Red is good 期望DP
题目大意 桌面上有\(R\)张红牌和\(B\)张黑牌,随机打乱顺序后放在桌面上,开始一张一张地翻牌,翻到红牌得到\(1\)美元,黑牌则付出\(1\)美元.可以随时停止翻牌,在最优策略下平均能得到多少钱 ...
- Rainbond v5.1.2发布,微服务架构应用便捷管理和交付
Rainbond v5.1.2发布,微服务架构应用便捷管理和交付 Rainbond是开源的企业应用云操作系统,支撑企业应用的开发.架构.交付和运维的全流程,通过无侵入架构,无缝衔接各类企业应用,底层资 ...
- Scripting Languages 簡介
Scripting Languages 簡介 何謂 Scripting? 命令稿語言 scripting language 是什麼? 很難給一個嚴格的定義; 不妨看看最具代表性的幾個例子: perl, ...
- 学习1__STM32--FatFS之逻辑盘符与物理盘符
FatFS源代码中的函数逻辑关系 第一 调用函数 f_mount() result = f_mount(&fs, FS_VOLUME_NAND, ); /* Mount a logical d ...
- 540. Single Element in a Sorted Array
题目大意: 给你一个由小到大排好序的数组,里面只有一个数出现了一次,其他数都出现了两次,要求找出那个只出现一次的数,而且时间复杂度为O(logn) 题目思路: 说实话一开始没想到,因为几乎每个数都出现 ...
- Spring的核心
技术书籍这么多,每次好不容易读完一本,但总过不了多久就会遗忘.为了对抗,整理记录和回看,也是实属必要.由此,从这<Spring 实战(第四版)>开始,记录一下知识点,下次再要复习时,能免去 ...
- 一张图看懂JVM
https://mp.weixin.qq.com/s?__biz=MzAxNjk4ODE4OQ==&mid=2247484432&idx=1&sn=381c98c49ffb81 ...