Luogu5058 [ZJOI2004]嗅探器

\(\verb|Luogu5058 [ZJOI2004]嗅探器|\)

给定一张 \(n\) 个点, \(m\) 条边的无向图,和两点 \(s,\ t\) ,求 \(s\to t\) 编号最小的必经点(排除 \(s,\ t\) )

\(n\leq100\)

tarjan



这题数据范围是可以 \(O(n^3)\) 暴力过的……

显然只需缩点后的树上 \(bl_s\) 到 \(bl_t\) 上找答案,统计割点贡献即可

然而此题有更简单的做法……

从 \(s\) 开始 tarjan,点 \(u\) 对答案有贡献当且仅当满足以下四个条件:

  1. \(u\neq s,\ t\)
  2. \(cut_u=\operatorname{true}\)
  3. \(dfn_v\leq dfn_t\) ,因为终点必须在 \(u\) 之后访问到
  4. \(dfn_u\leq low_t\) ,因为路径必须要经过 \(u\) 点

然后上板子

时间复杂度 \(O(n+m)\)

这份代码是缩点后统计链的……

#include <bits/stdc++.h>
using namespace std;

const int maxn = 110, inf = INT_MAX;
bool cut[maxn];
int n, m, A, B, h[maxn], q[maxn << 1], pre[maxn << 1];
int top, dcc, tot, st[maxn], bl[maxn], dfn[maxn], low[maxn];

struct edges {
  int nxt, to;
  edges(int x = 0, int y = 0) :
    nxt(x), to(y) {}
} e[maxn * maxn * 2];

vector <int> E[maxn << 1], d[maxn];

void addline(int u, int v) {
  static int cnt;
  e[++cnt] = edges(h[u], v), h[u] = cnt;
}

void tarjan(int u, int f) {
  static int now;
  st[++top] = u;
  dfn[u] = low[u] = ++now;
  if (!f && !h[u]) {
    d[++dcc].push_back(u);
    return;
  }
  for (int i = h[u], chd = 0; i; i = e[i].nxt) {
    int v = e[i].to;
    if (!dfn[v]) {
      tarjan(v, 1);
      low[u] = min(low[u], low[v]);
      if (dfn[u] <= low[v]) {
        cut[u] |= f || chd++;
        for (dcc++; st[top + 1] != v; top--) {
          d[dcc].push_back(st[top]);
        }
        d[dcc].push_back(u);
      }
    } else {
      low[u] = min(low[u], dfn[v]);
    }
  }
}

int bfs(int S, int T) {
  if (S == T) return inf;
  int l = 1, r = 1;
  q[1] = S, pre[S] = -1;
  while (l <= r) {
    int u = q[l++];
    for (int v : E[u]) {
      if (!pre[v]) {
        q[++r] = v, pre[v] = u;
      }
    }
  }
  int res = inf;
  for (int u = pre[T]; u != S; u = pre[u]) {
    if (u > dcc) res = min(res, u);
  }
  return res;
}

int main() {
  scanf("%d", &n);
  int u, v;
  while (scanf("%d %d", &u, &v) && u && v) {
    addline(u, v), addline(v, u);
  }
  scanf("%d %d", &A, &B);
  for (int i = 1; i <= n; i++) {
    if (!dfn[i]) tarjan(i, 0);
  }
  tot = dcc;
  for (int i = 1; i <= n; i++) {
    if (cut[i]) bl[i] = ++tot;
  }
  for (int i = 1; i <= dcc; i++) {
    for (int j = 0, _sz = int(d[i].size()); j < _sz; j++) {
      int x = d[i][j];
      if (cut[x]) {
        E[i].push_back(bl[x]);
        E[bl[x]].push_back(i);
      } else {
        bl[x] = i;
      }
    }
  }
  int res = bfs(bl[A], bl[B]);
  if (res > 1e9) {
    puts("No solution");
  } else {
    for (int i = 1; i <= n; i++) {
      if (cut[i] && bl[i] == res) {
        printf("%d", i); break;
      }
    }
  }
  return 0;
}

原文地址:https://www.cnblogs.com/Juanzhang/p/10660452.html

时间: 2024-10-15 19:04:01

Luogu5058 [ZJOI2004]嗅探器的相关文章

题解 P5058 【[ZJOI2004]嗅探器】

Solution [ZJOI2004]嗅探器 题目大意:给定一个无向图,求一个编号最小的点\(p\),使得删掉\(p\)后\(s\)和\(t\)不连通 分析:首先我们要明确:点\(p\)一定是割点,因为只有你删掉一个点后图不连通才有可能使得\(s\)和\(t\)不连通,然后我们可以用\(tarjan\)来做这个事情 常规求割点是什么,时间戳\(dfn\),不经过树边可以到达的最小时间戳\(low\) 如果存在\(u\)以及它的子节点\(v\),如果有\(dfn[u] \leq low[v]\)那

[zjoi2004]嗅探器

某军搞信息对抗实战演习.红军成功地侵入了蓝军的内部网络. 蓝军共有两个信息中心.红军计划在某台中间服务器上安装一个嗅探器,从而能够侦听到两个信息中心互相交换的所有信息.但是蓝军的网络相当的庞大,数据包从一个信息中心传到另一个信息中心可以不止有一条通路.现在需要你尽快地解决这个问题.应该把嗅探器安装在哪个中间服务器上才能保证所有的数据包都能被捕获? 题解:tarjan的简单应用: #include<iostream> #include<cstdio> #include<cstd

P5058 [ZJOI2004]嗅探器 tarjan割点

这个题是tarjan裸题.最后bfs暴力找联通块就行.(一开始完全写错了竟然得了70分,题意都理解反了...这数据强度...) 题干: 题目描述 某军搞信息对抗实战演习,红军成功地侵入了蓝军的内部网络,蓝军共有两个信息中心,红军计划在某台中间服务器上安装一个嗅探器,从而能够侦听到两个信息中心互相交换的所有信息,但是蓝军的网络相当的庞大,数据包从一个信息中心传到另一个信息中心可以不止有一条通路.现在需要你尽快地解决这个问题,应该把嗅探器安装在哪个中间服务器上才能保证所有的数据包都能被捕获? 输入输

【ZJOI2004】嗅探器

练tarjian不错的题,连WA几次后终于会记住tarjian的模板了 原题: 某军搞信息对抗实战演习.红军成功地侵入了蓝军的内部网络.蓝军共有两个信息中心.红军计划在某台中间服务器上安装一个嗅探器,从而能够侦听到两个信息中心互相交换的所有信息.但是蓝军的网络相当的庞大,数据包从一个信息中心传到另一个信息中心可以不止有一条通路.现在需要你尽快地解决这个问题.应该把嗅探器安装在哪个中间服务器上才能保证所有的数据包都能被捕获? 1<=n<=100000 恩,首先可以确定答案一定是割顶中的某个点,必

浏览器嗅探器【检测】

在前端开发中经常会遇到一系列兼容性问题,怎样精准地识别出各个浏览器的版本是一件很头痛的问题.下面跟大家分享图个非常实用的浏览器嗅探器的插件,可以让我们在开发中针对各种浏览器作出不同的流程控制.实现浏览器兼容. 代码如下: var BrowserDetect = { init: function () { this.browser = this.searchString(this.dataBrowser) || "An unknown browser"; this.version = t

Python写的嗅探器——Pyside,Scapy

使用Python的Pyside和Scapy写的嗅探器原型,拥有基本框架,但是功能并不十分完善,供参考. 1 import sys 2 import time 3 import binascii 4 from PySide.QtCore import * 5 from PySide.QtGui import * 6 from scapy.all import * 7 8 # Every Qt application must have one and only one QApplication o

浏览器简易嗅探器

document.write(navigator.userAgent); document.write('<br/>'); document.write(navigator.platform); var client = function(){ //引擎 var engine = { ie:false, gecko:false, khtml:false, opera:false, webkit:false, ver:0 }; //浏览器 var browser = { ie:false, fi

矩阵乘法专题3——bzoj 1898 [Zjoi2004]Swamp 沼泽鳄鱼 题解

[原题] 1898: [Zjoi2004]Swamp 沼泽鳄鱼 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 425  Solved: 256 [Submit][Status] Description 潘塔纳尔沼泽地号称世界上最大的一块湿地,它地位于巴西中部马托格罗索州的南部地区.每当雨季来临,这里碧波荡漾.生机盎然,引来不少游客.为了让游玩更有情趣,人们在池塘的中央建设了几座石墩和石桥,每座石桥连接着两座石墩,且每两座石墩之间至多只有一座石桥.这

PYTHON黑帽编程 4.1 SNIFFER(嗅探器)之数据捕获--补充

荒废了一个多月了,重新捡起来,手生了不少.发现在<4.1下>的文章里没有 提到pcap库,实在是不应该. 在网络数据分析的工具中,tcpdump绝对是大名鼎鼎,tcpdump底层是libpcap库,由C语言编写. Pcapy模块则是基于libpcap的Python接口.pcapy在github上的项目地址为: https://github.com/CoreSecurity/pcapy. 下面我们来看看如何使用pcapy实现数据包的捕获. #!/usr/bin/python import pca