hdu_4635
題目大意:給出一張dag(n個點,m條邊),求出能加的最大邊數,使得該圖無重邊,無自環,非強連通。
題解:這題題面很好理解,也沒有什麼很難的點,主要是如何求出最大邊數需要動點腦筋。首先要明確一點強連通圖不一定是完全圖,完全圖一定是強連通圖。因為完全圖定義是任意兩點均有連邊,而強連通僅為任意兩點可互相到達。於是乎這題我們可以這樣構思,最後我們要的是這樣一張圖,有若干條有向邊,連線著兩張完全子圖,那麼問題就來了,如何構造這兩張完全子圖?不妨設這兩張完全子圖為g1,g2,其頂點數分別為v1,v2(v1+v2=n),可知邊數為v1*v2+v1*(v1-1)+v2*(v2-1)
,v1*v2即為上文所言若干條邊,剩餘兩項即為g1,g2完全圖的邊數。化簡可得n*(n-1)-(n-v1)*v1
,注意這不是答案,因為題目給了m條邊,所以還要扣除m,那麼問題就來了,如何使得答案——n*(n-1)-m-(n-v1)*v1
最大?其實很容易想到,因為n,m是常數,所以v1就是關鍵,而v1+v2=n
那麼上式中n-v1
即為v2
,那麼如何使v1*v2
最小?由基本不等式(a^2 + b^2 >= 2ab
),可得,我們應該使v1、v2差值盡量大,那麼就可以統計一下各個強連通分量的大小,使最小的為v1
,然後帶入n*(n-1)-m-(n-v1)*v1
,就解決完了本題。其實就是有多個強連通分量,選最小的並且出度或者入度為0的當v1,剩下的去拼成一張完全圖,就得到了g1、g2,然後就是上述說明了。
對於入度或者出度為0的解釋:因為我們的構想是要兩張完全子圖g1、g2,然後g1、g2之間的若干條邊,均用g1(g2)指向g2(g1),所以如果橋上有點,應該歸入與之相連的較大的完全子圖中。
#include #include #include #include #include #define mem(a,b) memset((a),(b),sizeof(a))
using namespace std;
const int n = 1e5 + 16;
const int inf = 0x3f3f3f3f;
typedef long long ll;
struct edge
;edge edge[n<<1];
bool vis[n];
int sta[n], dfn[n], low[n];
int ecnt, head[n];
int in[n], out[n], cnt[n];
int col[n], sum, dep, top;
void init()
void _add( int _u, int _v )
void tarjan( int u )
else
if ( vis[v] )
}if ( low[u] == dfn[u] )
top --; }}
int main()
for ( int i = 1; i <= n; i ++ )
if ( !dfn[i] )
tarjan(i);
for ( int i = 1; i <= n; i ++ )
}}
if ( sum == 1 )
else
}return 0;
}
Graph Master 連通分量 D
hdu 2242 題目大意 求將一張無向圖 n個點,m條邊 移除一條邊分為不連通兩部分,使得兩部分的點權和最接近,若無法分為兩部分,則輸出impossible。題解 拿到題面還算清晰,就是先tarjan縮點,因為邊雙連通分量肯定無法移除一條邊使得分為不連通的兩部分 因為是無向圖 然後重新建圖,附好點...
BFS 連通分量 求連通分量
題目描述 求乙個圖的連通分量 input n 頂點數 100 邊 以0 0作為結束標誌 output 連通分量 強連通圖的連通分量為其本身。如果為非連通圖,則連通分量為該圖的最大連通子圖。分析 建乙個100 100的布林矩陣,b x,y true表示x與y連通。同時還要記錄該點是否被遍歷過 然後遍歷...
點連通分量 邊連通分量 割點和橋 強連通分量
老是搞不清他們的關係,不知道該用那份 今天理了一下,整理一下模板 點連通分量 可以求出點連通分量包含哪些點,那個點屬於那個連通分量 struct edge int pre maxn iscut maxn bccno maxn dfs clock,bcc cnt vectorg maxn bcc ma...