P5058 [ZJOI2004]嗅探器 tarjan割点

Posted dukelv

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P5058 [ZJOI2004]嗅探器 tarjan割点相关的知识,希望对你有一定的参考价值。

这个题是tarjan裸题。最后bfs暴力找联通块就行。(一开始完全写错了竟然得了70分,题意都理解反了。。。这数据强度。。。)

题干:

题目描述

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

输入文件的第一行一个整数 n,表示蓝军网络中服务器的数目。

接下来若干行是对蓝军网络的拓扑结构描述,每行是两个整数 i , j 表示编号为 i 和编号为 j 的两台服务器间存在连接(显然连接是双向的),服务器的编号从 1 开始,一行两个 0 表示网络的拓补结构描述结束,再接下来是两个整数 a , b 分别表示两个中心服务器的编号。

输出格式:

输出编号。如果有多个解输出编号最小的一个,如果找不到任何解,输出 No solution

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(register int i = a;i <= n;++i)
#define lv(i,a,n) for(register int i = a;i >= n;--i)
#define clean(a) memset(a,0,sizeof(a))
const int INF = 1 << 30;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < 0 || c > 9)
        if(c == -) op = 1;
    x = c - 0;
    while(c = getchar(), c >= 0 && c <= 9)
        x = x * 10 + c - 0;
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar(-), x = -x;
    if(x >= 10) write(x / 10);
    putchar(0 + x % 10);
}
const int N = 1e5 + 5;
struct node
{
    int l,r,nxt;
}a[N * 5];
int n,A,B;
int x,y;
int lst[N],len,cnt = 0,dfn[N],low[N];
int cut[N],child = 0;
void add(int x,int y)
{
//    cout<<x<<" "<<y<<endl;
    a[++len].l = x;
    a[len].r = y;
    a[len].nxt = lst[x];
    lst[x] = len;
}
void tarjan(int x,int fa)
{
    dfn[x] = low[x] = cnt++;
    for(int k = lst[x];k;k = a[k].nxt)
    {
        int y = a[k].r;
        if(!dfn[y])
        {
            tarjan(y,x);
            low[x] = min(low[x],low[y]);
            if(low[y] >= dfn[x] && x != fa)
            {
                cut[x] = 1;
            }
            if(x == fa)
            {
                child++;
            }
        }
        low[x] = min(low[x],dfn[y]);
    }
    if(child >= 2 && x == fa)
    {
        cut[x] = 1;
    }
}
bool vis[N];
bool check(int x)
{
    clean(vis);
    queue <int> q;
    vis[A] = 1;
    q.push(A);
    while(!q.empty())
    {
        int now = q.front();
        q.pop();
//        cout<<now<<"???"<<endl;
        if(now == x) continue;
        for(int k = lst[now];k;k = a[k].nxt)
        {
            int y = a[k].r;
            if(vis[y] == 1) continue;
            if(y == x) continue;
            if(y == B) return false;
            vis[y] = 1;
            q.push(y);
        }
    }
    return true;
}
int main()
{
    read(n);
    while(1)
    {
        read(x);read(y);
        if(x == 0 && y == 0)
        {
            break;
        }
        add(x,y);
        add(y,x);
    }
    read(A);read(B);
    duke(i,1,n)
    {
        if(!dfn[i])
        {
            tarjan(i,i);
        }
    }
    duke(i,1,n)
    {
        if(i == A || i == B) continue;
        if(cut[i])
        {
//            cout<<i<<endl;
            if(check(i) == true)
            {
                printf("%d
",i);
                return 0;
            }
        }
    }
    printf("No solution
");
    return 0;
}

 

以上是关于P5058 [ZJOI2004]嗅探器 tarjan割点的主要内容,如果未能解决你的问题,请参考以下文章

[zjoi2004]嗅探器

ZJOI2004嗅探器

网络嗅探器怎么用啊?

如何防止嗅探器的探测?

Python写的嗅探器——Pyside,Scapy

Python黑帽编程 4.1 Sniffer(嗅探器)之数据捕获(上)