hdu 3849 By Recognizing These Guys, We Find Social Networks Useful

本文介绍了一个基于Tarjan算法实现的无向图割点和桥检测的C++程序。该程序通过特定的数据结构和算法来找出图中的所有桥,并按输入顺序输出这些桥对应的边。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

判断无向图的割点和桥的模板题,但是这个题要求按照输入的顺序输出边,因此需要把边保存以下,挺麻烦的其实,= =。

#include <map>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int MAX = 10010;

typedef pair <int, int> Pii;
vector <int> vt[MAX];
vector <Pii> ans;
map <string, int> mp;
map <Pii, int> order;
string a, b, name[MAX];

int n, m;
bool vis[MAX];
int cnt_n, cnt_e,dfs_clock;
int pre[MAX];
void init(){
    for(int i=1; i<=n; i++){
        vt[i].clear();
        pre[i] = 0;
        vis[i] = false;
    }
    mp.clear();
    ans.clear();
    order.clear();
    cnt_e = cnt_n = dfs_clock = 0;
}

void is_connected(int u){//判断是否连通
    vis[u] = true;
    for(int i=0; i<vt[u].size(); i++){
        int v = vt[u][i];
        if(!vis[v]) is_connected(v);
    }
}

bool presolve(){
    for(int i=1; i<=n; i++)
        if(!vis[i]) return false;
    return true;
}

int dfs(int u, int fa){//tarjan算法求桥
    int lowu = pre[u] = ++dfs_clock;
    for(int i=0; i<vt[u].size(); i++){
        int v = vt[u][i];
        if(!pre[v]){
            int lowv = dfs(v, u);
            lowu = min(lowu, lowv);
            if(lowv > pre[u]){
                Pii tmp;
                tmp.first = u, tmp.second = v;
                if(order[tmp] == false) 
                    tmp.first = v, tmp.second = u;
                ans.push_back(tmp);
            }
        }
        else if(pre[v] < pre[u] && v != fa)
            lowu = min(lowu, pre[v]);
    }
    return lowu;
}

bool cmp(Pii A, Pii B){
    return order[A] < order[B];
}

int main(){
    int cas;
    scanf("%d",&cas);
    while(cas--){
        scanf("%d%d",&n,&m);
        init();
        for(int i=0; i<m; i++){
            cin >> a >> b;
            if(mp[a] == false){
                mp[a] = ++cnt_n;
                name[cnt_n] = a;
            }
            if(mp[b] == false){
                mp[b] = ++cnt_n;
                name[cnt_n] = b;
            }
            int u = mp[a], v = mp[b];
            vt[u].push_back(v);
            vt[v].push_back(u);
            Pii tmp;
            tmp.first = u, tmp.second = v;
            order[tmp] = ++cnt_e;
        }
        is_connected(1);
        if(!presolve()){
            puts("0");
            continue;
        }
        dfs(1, -1);
        int l = ans.size();
        printf("%d\n",l);
        sort(ans.begin(), ans.end(), cmp);
        for(int i=0; i<l; i++){
            cout << name[ans[i].first] << " " << name[ans[i].second] << endl;
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值