1. 程式人生 > >uvalive5796(圖論、橋、並查集)

uvalive5796(圖論、橋、並查集)

題意:

給出一個無向圖,每次詢問,問兩個點之間是否有一條唯一的不經過重複點的路徑。

思路:

如果存在這樣的路徑,那麼路徑上的點就都是橋,我們可以找出圖中所有的橋,把非橋邊刪去,把橋連的點塞到並查集中,查詢的時候每次只要看兩個點是否在同一個並查集即可。

這題比賽的時候沒過,賽後也沒寫,貼一個我們校一隊的程式碼吧。

程式碼:

#include<iostream>
#include<map>
#include<vector>
#include<string.h>
#include<stdio.h>
using namespace std;
const int maxa = 10005;
vector<int> e[maxa];
map<int, bool> mp[maxa];
bool cut[maxa];
int low[maxa], dfn[maxa], vis[maxa];
void cut__(int cur, int father, int dep, int n){
    vis[cur] = 1;dfn[cur] = low[cur] = dep;
    int children = 0;
    for(int k = 0;k < e[cur].size(); k++){
        int i = e[cur][k];
        if(i != father && 1 == vis[i]){
            if(dfn[i] < low[cur]){
                low[cur] = dfn[i];
            }
        }
        if(0 == vis[i]){
            cut__(i , cur, dep+1, n);
            children ++;
            if(low[i] < low[cur]) low[cur] = low[i];
            if((father == -1 && children > 1) || father != -1 && low[i] >= dfn[cur]) cut[cur] = true;
            if(low[i] > dfn[cur]){
                mp[cur][i] = mp[i][cur] = 1;
               // printf("*------%d %d\n", cur, i);
            }
        }
    }
    vis[cur] = 2;
}
int fa[maxa];
int find(int ii){
    return fa[ii] = fa[ii] == ii? ii:find(fa[ii]);
}
int main(){
    int r, c, q;
    while(scanf("%d%d%d", &r, &c, &q), r||c||q){
        for(int i = 0;i <= r; i++){
            e[i].clear();
            mp[i].clear();
        }
        for(int i = 1;i <= r; i++){
            fa[i] = i;
        }
        memset(cut, 0, sizeof(cut));
        memset(vis, 0, sizeof(vis));
        memset(low, 0, sizeof(low));
        memset(dfn, 0, sizeof(dfn));
        for(int i = 0;i < c; i++){
            int u, v;
            scanf("%d%d", &u, &v);
            e[u].push_back(v);
            e[v].push_back(u);
        }
        for(int i = 1; i <= r; i++){
            if(vis[i] == 0){
                cut__(i, -1, 0, r);
            }
        }
        for(int i = 1; i <= r; i++){
            for(int k = 0; k< e[i].size(); k++){
                if(mp[i][e[i][k]] == 1){
                    fa[find(i)] = find(e[i][k]);
                    //printf("%d %d ------\n", i, e[i][k]);
                }
            }
        }
        while(q--){
            int u, v;
            scanf("%d%d", &u, &v);
            if(find(u) == find(v)){
                puts("Y");
            }else{puts("N");
            }
        }puts("-");
    }
}


相關推薦

題目模板,和:以後的題目就靠他了

fat union 一次 情況 返回 end empty 是我 min ‘‘‘ 並查集: 1.用於查如何A,B是否在一個集合中. 2.每一個集合設立一個頭結點.其他都連向他 3.集合合並就是把小的集合掛到大的集合下面即可 4.優化.查詢到一個a在b這個頭結點下面,那麽直

BZOJ4025 二分(線段樹分治+

data cto 距離 har oid bsp find vector 節點 之前學了一下線段樹分治,這還是第一次寫。思想其實挺好理解,即離線後把一個操作影響到的時間段拆成線段樹上的區間,並標記永久化。之後一塊處理,對於某個節點表示的時間段,影響到他的就是該節點一直到線段樹

leetcode684+刪除樹中構成的多餘邊,

https://leetcode.com/problems/redundant-connection/description/ class Solution { public: int find(int a, int p[]) { int res = a;

[BZOJ4025] 二分 LCT/(線段樹分治+)

4025: 二分圖 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2667  Solved: 989[Submit][Status][Discuss] Descrip

1013 Battle Over Cities (25 分)(的遍歷or)

這題用並查集或者dfs都可以做   dfs #include<bits/stdc++.h> using namespace std; const int N=1e3+10; bool mp[N][N]; int n,m,k; bool vis[N]; void dfs(in

哥尼斯堡的“七問題“()

無向圖存在歐拉回路的充要條件       一個無向圖存在歐拉回路,當且僅當該圖所有頂點度數都為偶數,且該圖是連通圖。有向圖存在歐拉回路的充要條件       一個有向圖存在歐拉回路,所有頂點的入度等於出

uvalive5796()

題意: 給出一個無向圖,每次詢問,問兩個點之間是否有一條唯一的不經過重複點的路徑。 思路: 如果存在這樣的路徑,那麼路徑上的點就都是橋,我們可以找出圖中所有的橋,把非橋邊刪去,把橋連的點塞到並查集中,查詢的時候每次只要看兩個點是否在同一個並查集即可。 這題比賽的時候沒過,

c++求連通個數,以及最大連通節點個數位元組跳動例題的實現

輸入:第一行輸入兩個數n(表示n行),m(表示m列) 接下來輸入n行m列的矩陣 輸出:連通圖個數 最大連通圖節點數 例子:輸入: 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 1 0 0 0 0 0 1 0 1 1 0

《演算法筆記》10. 相關演算法看完這篇不能再說不會了。

[TOC] # 1 並查集、圖相關演算法 > 轉載註明出處,原始碼地址: https://github.com/Dairongpeng/algorithm-note ,歡迎star ## 1.1 並查集 ### 1.1.1 並查集基本結構和操作 1、有若干個樣本a、b、c、d...型別假設是V

1013. Battle Over Cities (25)(連通分量個數 )

mage conn pen view con input case scanf print It is vitally important to have all the cities connected by highways in a war. If a city is

51Nod 1515(set離散化)

() space 並查集 conn com i++ include int esp //代碼還是YY學姐幫改的,自己從來沒有真正A過幾道題,不是看題解就是有BUG找不出,多久了還是改變不了這樣的現狀,或許ACM就是這麽篩選人的吧。從5.24到11.24,再到又一年的5.24

NO.9章 樹(遍歷BSTAVL哈夫曼)

ack bst 路徑壓縮 層序遍歷 查找樹 哈夫曼樹 平衡 style 操作 1. 樹與二叉樹 1)定義性質 3)存儲 4)基本操作 2. 二叉樹的遍歷 1)先序 2)中序 3)後序 4)層序 5)二叉樹靜態實現 3. 樹的遍歷 1)二叉樹靜態實現 2)先根遍歷 3)

hdu 1863 暢通工程 ( kruskal)

temp 編號 set queue bits 統計表 script pri with 暢通工程Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S

【hiho】14 無間道之--

const lse string turn problem scan -c for sca 傳送門:無間道之並查集 分析 並查集的分析可以看上面的傳送門,寫的挺好的了。 其實在我看來並查集就是一種方便的維護集合的一種技巧,提出了代表元素這一概念。 My AC Code #i

Virtual Friends 【HDU - 3172】【帶權】【題目不難但有坑點】

題目連結   為什麼能這麼埋坑???我還以為我錯了,結果找不到BUG,後來一看Discuss,發現竟是這種問題。。。   一般情況,我們都是while(T--)就行,但這道題可真就不一樣了,它還需要while(scanf("%d", &T)!=EOF)!

牛客練習賽32 D Tarjan無向+維護

題目描述: 小p和他的朋友約定好去遊樂場遊玩,但是他們到了遊樂場後卻互相找不到對方了。 遊樂場可以看做是一張n個點,m條道路的圖,每條道路有邊權wi,表示第一次經過該道路時的花費(第二次及以後經過時花費為0)。 現在,小p要去找他的朋友,但他的朋友行蹤很詭異,小p總是要遍歷完這n個點才能找到他,

簡要題解--搜尋--dp-樹形-拓撲-tarjan等等

attentions:對我而言非常好的一道題!最長路! 有幾個點 1、這道題轉化成最長路來求解,方法和最短路類似 2、但這道題是點有正權且只有負權邊,且路徑為單向!那麼精妙之處在於,可以將點權轉化為邊權!!! 3、由於題目中可能出現正環(和最短路相反

【NOJ159315941595】【三連】朋友敵人關係

1593.並查集(一) 時限:1000ms 記憶體限制:10000K  總時限:3000ms 描述 一個城市中有n個人,其中一些人是朋友關係,同時他們都認為:朋友的朋友是朋友,現在任給兩個人,問他們是否是朋友關係。 輸入 先輸入兩個正整數n和m(均小於1000),表

PTA 中國大學MOOC-陳越何欽銘-資料結構-2018秋 05-樹8 File Transfer (25 分)

We have a network of computers and a list of bi-directional connections. Each of these connections allows a file transfer from one compute

3172】【帶權】【題目不難但有坑點】

題目連結   為什麼能這麼埋坑???我還以為我錯了,結果找不到BUG,後來一看Discuss,發現竟是這種問題。。。   一般情況,我們都是while(T--)就行,但這道題可真就不一樣了,它還需要while(scanf("%d", &T)!=EOF)!!!