• UVA10972


    题目链接


    题意: 给定一个无向图,问最少加入多少条边,使得这个图成为连通图

    思路:首先注意题目给出的无向图可能是非连通的,即存在孤立点。处理孤立点之后。其它就能够当作连通块来处理。事实上跟POJ3352非常像,仅仅只是存在孤立点而已。所以找出桥,缩点,然后统计度数为0(伸出两条边)的点u和度数为1(伸出一条边)的点。最后的答案为(2 * u + v + 1) / 2。

    POJ3352

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <utility>
    #include <algorithm>
    
    using namespace std;
    
    const int MAXN = 1005;
    
    struct Edge{
        int to, next;
    }edge[MAXN * 100];
    
    int head[MAXN], tot;
    int Low[MAXN], DFN[MAXN], dg[MAXN], used[MAXN];
    int Index;
    int bridge;
    
    void addedge(int u, int v) {
        edge[tot].to = v;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    
    void Tarjan(int u, int pre) {
        int v;  
        Low[u] = DFN[u] = ++Index;  
        for (int i = head[u]; i != -1; i = edge[i].next) {  
            v = edge[i].to;  
            if (v == pre) continue;   
            if (!DFN[v]) {  
                Tarjan(v, u);   
                if (Low[u] > Low[v]) 
                    Low[u] = Low[v];  
                if (Low[v] > DFN[u])
                    bridge++;
            }   
            else if (Low[u] > DFN[v])  
                Low[u] = DFN[v];  
        }  
    }
    
    void init() {
        memset(head, -1, sizeof(head));
        memset(DFN, 0, sizeof(DFN)); 
        memset(Low, 0, sizeof(Low)); 
        Index = tot = 0;
        bridge = 0;
    }
    
    void solve(int N) {
        for (int i = 1; i <= N; i++)
            if (!DFN[i]) {
                Tarjan(i, i);
                bridge++;
            }
    
        if (bridge == 1) {
            printf("0
    "); 
        }
        else {
            memset(used, 0, sizeof(used));
            memset(dg, 0, sizeof(dg)); 
            for (int u = 1; u <= N; u++) {
                if (head[u] == -1) {
                    used[Low[u]] = 1;
                    continue;
                }
                for (int i = head[u]; i != -1; i = edge[i].next) {
                    int v = edge[i].to; 
                    used[Low[u]] = used[Low[v]] = 1;
                    if (Low[u] != Low[v]) {
                        dg[Low[u]]++; 
                    }
                }
            }
    
            int ans = 0;
            for (int u = 1; u <= N; u++) {
                if (used[u] && dg[u] == 0) ans += 2; 
                else if (dg[u] == 1) ans++; 
            }
            ans = (ans + 1) / 2;
            printf("%d
    ", ans);
        }
    }
    
    int main() {
        int n, m; 
        while (scanf("%d%d", &n, &m) != EOF) {
            init(); 
            int u, v;
            while (m--) {
                scanf("%d%d", &u, &v); 
                addedge(u, v);
                addedge(v, u);
            }
            solve(n);
        }
        return 0;
    }
    



  • 相关阅读:
    Word Puzzles [POJ 1204]
    set用法
    FOJ有奖月赛2012年11月
    BerDonalds
    POJ1469 匈牙利算法
    后缀数组
    ZOJ Monthly, January 2013
    算法导论<一>
    Yell Classico
    点聚 WebOffice 编辑辅助控件 WebOffice.OCX
  • 原文地址:https://www.cnblogs.com/blfshiye/p/5217930.html
Copyright © 2020-2023  润新知