poj 3177 3352 有重邊的邊連通分量

2021-07-28 04:57:17 字數 1580 閱讀 9352

為了保護放牧環境,避免牲畜過度啃咬同乙個地方的草皮,牧場主決定利用不斷遷移牲畜進行餵養的方法去保護牧草。然而牲畜在遷移過程中也會啃食路上的牧草,所以如果每次遷移都用同一條道路,那麼該條道路同樣會被啃咬過度而遭受破壞。

現在牧場主擁有f個農場,已知這些農場至少有一條路徑連線起來(不一定是直接相連),但從某些農場去另外一些農場,至少有一條路可通行。為了保護道路上的牧草,農場主希望再建造若干條道路,使得每次遷移牲畜時,至少有2種遷移途徑,避免重複走上次遷移的道路。已知當前有的r條道路,問農場主至少要新建造幾條道路,才能滿足要求?

3352和3177的題意一樣,都是邊連通分量,縮點,然後根據得到的樹去計算。

乙個有橋的連通圖,如何把它通過加邊變成邊雙連通圖?方法為首先求出所有的橋,然後刪除這些橋邊,剩下的每個連通塊都是乙個雙連通子圖。把每個雙連通子圖收縮為乙個頂點,再把橋邊加回來,最後的這個圖一定是一棵樹,邊連通度為1。

統計出樹中度為1的節點的個數,即為葉節點的個數,記為leaf。則至少在樹上新增(leaf+1)/2條邊,就能使樹達到邊二連通,所以至少新增的邊數就是(leaf+1)/2。具體方法為,首先把兩個最近公共祖先最遠的兩個葉節點之間連線一條邊,這樣可以把這兩個點到祖先的路徑上所有點收縮到一起,因為乙個形成的環一定是雙連通的。然後再找兩個最近公共祖先最遠的兩個葉節點,這樣一對一對找完,恰好是(leaf+1)/2次,把所有點收縮到了一起。

要注意的是3352有重邊。

模板來自:

/*

可以有重邊

*/#include

#include

#include

#include

#include

using

namespace

std;

typedef

long

long ll;

const

int n=5e3+7;

int m, n, dfs_cnt, ecc_cnt, top;

int pre[n], ecc[n], low[n], pa[n], stack[n];

vector

g[n];

void init()

void tarjan(int u,int fa)

if(!low[v]) else

low[u] = min(low[u], pre[v]);

}if(pre[u] == low[u]) while(u != v);

ecc_cnt ++;

}}void solve() , ans = 0;

for(i=1; i<=n; i++)

for(i=1; i<=n; i++)

}// for(int i=1; i<=n; i++)printf("%d\n",ecc[i]);

for(i=0; iif(degree[i] == 1)

ans ++;

}printf("%d\n", (ans+1)/2 );

}int main()

solve();

}return

0;}

POJ 2485 Prim 找最長的邊

a國沒有高速公路,因此a國的交通很困難。意識到了這個問題並且計畫建造一些高速公路,以至於可以在不離開高速公路的情況下在任意兩座城鎮之間行駛。a國的城鎮編號為1到n,每條高速公路連線這兩個城鎮,所有高速公路都可以在兩個方向上使用。高速公路可以自由的相互交叉。a國 希望儘量減少最長高速公路的建設時間 使...

陣列去重的方法有

var str newset 1 1 ss sdf 2 2 3 console.log str var a 1 2,3 4,34 1,1 1,3 4,5 5,4 2,4 5,2 宣告乙個空陣列 var b for var i 0 i a.length i if status 0 var arr 1 ...

POJ 3204 網路流的必須邊

思路 求一遍網路流 在殘餘網路上dfs 從起點dfs 從終點把邊反向dfs 乙個邊跟起點連通 跟終點反向的邊連通 ans 注 此題不能用tarjan 因為有邊權為0的邊 by siriusren include include include include using namespace std ...