SAFENET2 spoj – Mạng máy tính an toàn

Nguồn đề bài: http://vn.spoj.com/problems/SAFENET2/

1. Đề bài SAFENET2 spoj

Có n máy tính đánh số từ 1 đến n và m dây cáp mạng,giữa 2 máy tính có thể có một hoặc nhiều đường dây cáp mạng nối chúng,không có cáp mạng nối một máy với chính nó.Hai máy tính có thể truyền dữ liệu cho nhau nếu có đường cáp nối trực tiếp giữa chúng hoặc truyền qua một số máy trung gian.

Một tập S các máy tính được gọi là hệ thống an toàn nếu dù một máy tính bất kỳ bị tấn công (do sự tò mò của người dân :-(,cứ thích truy cập và hack những trang cấm 🙁 ) thì trong số những máy tính còn lại,những máy tính thuộc tập S vẫn có thể truyền được dữ liệu cho nhau. Xác định số lượng lớn nhất có thể các máy tính của tập S

Input

-Dòng 1 chứa 2 số nguyên n,m(1<=n<=30.000,0<=m<=100.000)

-m dòng tiếp theo ghi thông tin về các dây cáp mạng,gồm 2 chỉ số của 2 máy được dây đó nối trực tiếp

Output

Ghi một số nguyên duy nhất là số lượng máy tính lớn nhất tìm đc

Example

Input:
8 10
1 2
2 3
3 1
1 4
4 5
5 1
1 6
6 7
7 8
8 1
Output:
4

 

2. Hướng dẫn SAFENET2 spoj

Trước khi làm bài này, ta sẽ tìm hiểu về cấu tạo của đồ thị vô hướng. Đồ thị vô hướng chia thành các thành phần song liên thông. Các thành phần song liên thông được nối với nhau bởi các cầu.

hình ảnh tượng trưng

 

safenet: tập an toàn —— S là safenet -> song lt

——–S là song lt -> chưa chắc đã an toàn

=> N xét: mỗi tp song lt đc cấu tạo bởi các tập an toàn, gắn vs nhau qua các khớp.

=> ???? làm thế nào để tìm đc S?

  • num là số thự tự duyệt trong dfs
  • gọi low of 1 đỉnh là số hiệu nhỏ nhất of đỉnh kề vs đỉnh đó có num >= nó

u có 3 loại con:

  • low[v2]>num[u]:có 1 S với số đỉnh bằng số con of v2.
  • low[v3]=num[u]: có 1 S với số đỉnh bằng số con of v3+1 (đỉnh u).
  • low[v1]<num[u].

3. Code tham khảo SAFENET2 spoj

#include <bits/stdc++.h>
#define maxn 30001
#define maxm 100005
#define fs first
#define sc second
using namespace std;
typedef pair<int,int> II;
    int n,m,deg[maxn];
    vector<int> g[maxn];
    II ed[maxm];
    int s[maxn],cur[maxn],cl[maxn],pe[maxn],pre[maxn],num[maxn],low[maxn],x[maxn],id=0;
    int sl[maxn];
void dfs(int xp)
{
    int sn=0;
    s[++sn]=xp; cl[xp]=1;
    pe[xp]=pre[xp]=0;
    num[xp]=low[xp]=++id;
    x[id]=xp;
    while(sn)
    {
        int u=s[sn];
        if(cur[u]<deg[u])
        {
            int i=g[u][cur[u]++];
            if(abs(i)!=pe[u])
            {
                int v=(i>0)?ed[i].sc:ed[-i].fs;
                if(cl[v]==0)
                {
                    cl[v]=1; s[++sn]=v;
                    pe[v]=abs(i); pre[v]=u;
                    num[v]=low[v]=++id;
                    x[id]=v;
                } else low[u]=min(low[u],num[v]);
            }
        } else
        {
            int w=pre[u];
            if(w) low[w]=min(low[w],low[u]);
            --sn;
        }
    }
}
int main()
{
    //freopen("safenet.inp","r",stdin);
    //freopen("safenet.out","w",stdout);
    ios::sync_with_stdio(0);
    cin>>n>>m;
    for(int i=1; i<=m; i++)
    {
        int u,v;
        cin>>u>>v;
        ed[i]=II(u,v);
        deg[u]++; g[u].push_back(i);
        deg[v]++; g[v].push_back(-i);
    }
    for(int i=1; i<=n; i++)
        if(cl[i]==0) dfs(i);
    int ds=1;
    for(int j=n; j>=1; j--)
    {
        int u=x[j];
        for(int o=0; o<deg[u]; o++)
        {
            int i=g[u][o];
            int v=(i>0)? ed[i].sc:ed[-i].fs;
            if(abs(i)!=pe[v]) continue;
            if(sl[v]==0) continue;
            if(low[v]==num[u])
            {
                ds=max(ds,sl[v]+1);
                sl[v]=0;
            }
            else
            if(low[v]>num[u])
            {
                ds=max(ds,sl[v]+1);
                sl[v]=0;
            } else sl[u]+=sl[v];
        }
        sl[u]++;
    }
    cout<<ds;
}

nguồn: kienthuc24h.com-

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *