degree
http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=826&pid=1001
Accepts: 1581
Submissions: 3494
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
Problem Description
度度熊最近似乎在研究圖論。給定一個有 N 個點 (vertex) 以及 M 條邊 (edge) 的無向簡單圖 (undirected simple graph),此圖中保證沒有任何圈 (cycle) 存在。 現在你可以對此圖依序進行以下的操作: 1. 移除至多 K 條邊。 2. 在保持此圖是沒有圈的無向簡單圖的條件下,自由的添加邊至此圖中。 請問最後此圖中度數 (degree) 最大的點的度數可以多大呢?
Input
輸入的第一行有一個正整數 T ,代表接下來有幾筆測試資料。 對於每筆測試資料:第一行有三個整數 N , M , K 。接下來的 M 行每行有兩個整數 a 及 b ,代表點 a 及 b 之間有一條邊。點的編號由 0 開始至 N−1 。 * 0≤K≤M≤2×105 * 1≤N≤2×105 * 0≤a,b<N * 給定的圖保證是沒有圈的簡單圖 * 1≤T≤23 * 至多 2 筆測試資料中的 N>1000
Output
對於每一筆測試資料,請依序各自在一行內輸出一個整數,代表按照規定操作後可能出現的最大度數。
Sample Input
Copy
2 3 1 1 1 2 8 6 0 1 2 3 1 5 6 4 1 6 4 7 0
Sample Output
Copy
2 4
題解:
沒有圈 (cycle) 的簡單圖 (undirected simple graph),等價於由多顆樹 (tree) 組成的森林 (forest)。這裏用 V 代表點的數量,E 代表邊的數量 (取代題目中的 N 以及 M),C 代表森林中樹的數量。
## K=0 的 case 不妨先化簡一下題目,在 K=0 的狀態下要達到 degree 最大化,可以貪心的把森林中所有樹各自接一條邊到已知 degree 最大的點上。答案是 C + 已知最大的 degree - 1。
## K≥0 的 case 回到原題,題目中規定一定要在添加邊之前把拔邊的操作作完,但是實際上任意調換添加邊以及拔掉邊的順序不會影響最後的結果。考慮貪心添加完邊的樹,可以多拔掉一條邊再重新接上的效果等同於把答案 +1,要注意的是如果答案已經到達最大值 V-1 的話,那拔邊再接上並不會影響答案。所以答案為min(V - 1, K + C + 已知最大的 degree - 1)。
## 樹的數量 C = V - E 由於給定的圖是面數 (face) 爲 1 的平面圖 (planar graph),所以根據平面圖的公式 V-E+F=C+1 整理後 C=V-E。另外一個證明:圖中每個 connected component 都是由樹所組成,也就是說每個 component 中邊數會是點數 - 1,直接可推得 C=V?E。 有了 C=V-E 後,答案就變成 min(V - 1, K + V - E + 已知最大的 degree - 1)。也就是,我們其實不用真正的寫出計算 connected component 的算法,只要統計 degree 最大的點有多大就可以計算出答案了。 整個時間複雜度爲 O(V),注意這題中有 O(V)=O(E)。
代碼:
#include<iostream>
#include<cstring>
#include<cmath>
#include<iomanip>
#include<algorithm>
#include<cstdio>
#define inf 0x3f3f3f3f
using namespace std;
int s[200005];
int main()
{
int t;
int n,m,k;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&k);
memset(s,0,sizeof(s));
int a,b;
for(int i=0;i<m;i++)
{
cin>>a>>b;
s[a]++;
s[b]++;
}
int maxx=0;
for(int i=0;i<n;i++)
{
if(maxx<s[i])
maxx=s[i];
}
//cout<<" "<<maxx<<endl;
int c=n-m; //樹的數量
if(k==0)
cout<<c+maxx-1<<endl;
else
cout<<min(n-1,k+c+maxx-1)<<endl;
}
return 0;
}