Light OJ 1308 - Ant Network

来源:互联网 发布:阿里云机顶盒 编辑:程序博客网 时间:2024/06/04 01:28

题意:

给一个无向图,每个点都有蚂蚁,一旦摧毁掉某个点后,所有点上的蚂蚁必须都能跑到庇护所,问最少需要在多少个上安排庇护所使得,任意一个点摧毁后,所有蚂蚁都是安全的?

思路:

首先如果给定的图为一个连通块的话,那么至少需要2个点。
接下来就求一下图内的割点。
对于一个联通块内,如果有多于一个割点的话,这样是不需要放置庇护点的,因为只能摧毁掉一个点,我可以选择其他一个割点去庇护所。否则这个联通块内就需要放置庇护所了。

代码:

#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#include <iostream>#include <cmath>#include <map>#include <vector>#include <set>#include <string>#define PB push_back#define FT first#define SD second#define MP make_pair#define INF 0x3f3f3f3fusing namespace std;typedef long long LL;typedef unsigned long long ULL;typedef pair<int,int>  P;const int N = 5 + 1e4,M = 7+1e9;int n, m;int tot, head[N], resCut;int top, ord, DFN[N], low[N], st[N];bool instack[N], isCut[N];struct edge{    int to,next;}e[4*N];void init(){    tot = ord = top = resCut = 0;    memset(head, -1, sizeof(head));    memset(DFN, -1, sizeof(DFN));    memset(low, -1, sizeof(low));    memset(instack, 0, sizeof(instack));    memset(isCut, 0, sizeof(isCut));}void addedge(int u,int v){    e[tot].to = v, e[tot].next = head[u], head[u] = tot++;}void tarjan(int u, int fa){    DFN[u] = low[u] = ord ++;    instack[u] = 1;    st[top++] = u;    int child = 0;    for(int i = head[u];i != -1;i = e[i].next) {        int v = e[i].to;        if(v == fa) continue;        if(DFN[v] == -1){            child ++;            tarjan(v,u);            if(low[u] > low[v]){                low[u] = low[v];            }            if(fa == -1 && child > 1) isCut[u] = 1;            if(fa != -1 && low[v] >= DFN[u]) isCut[u] = 1;            resCut += isCut[u];        }        else if(instack[v]) {            low[u] = min(low[u], DFN[v]);        }    }}set<int> ss;bool vis[N];int cnt;void dfs(int u){    vis[u] = 1;    cnt ++;    for(int i = head[u];i != -1;i = e[i].next) {        int v = e[i].to;        if(isCut[v]) {            ss.insert(v);            continue;        }        if(isCut[v] || vis[v]) continue;        dfs(v);    }}int main(){    int T, u, v, ca = 0;    scanf("%d",&T);    while(T --){        scanf("%d%d",&n,&m);        init();        while(m --){            scanf("%d%d",&u,&v);            addedge(u,v), addedge(v,u);        }        tarjan(0,-1);        int ans1 = 0;        ULL ans2 = 1;        if(resCut == 0) {            ans1 = 2, ans2 = 1ULL * n * (n - 1) / 2;        }        else {            memset(vis, 0, sizeof(vis));            for(int i = 0;i < n;i ++) {                if(isCut[i] || vis[i]) continue;                ss.clear();                cnt = 0;                dfs(i);                if(ss.size() <= 1) {                    ans1 ++, ans2 *= cnt;                }            }        }        printf("Case %d: %d %llu\n", ++ca, ans1, ans2);    }    return 0;}
0 0
原创粉丝点击