传送门:
比赛时 我已经是想到是怎么做了,但是当时我就是短路还是傻逼了,可能是自己已经进入了复赛没有悬念了吧,
不然也不会这样犯了低级错误,不过也好,愚人千虑必有一得。我今天的确是想多了,本来就是这样做,
而自己的调代码的能力有待加强呀,连Long Long 这种错误都看不出来。我真的傻逼了。
这个第一题,我本来就对这个并查集不太熟悉,这一次比赛真的又把我逼着学了一回并查集。
真的好好感谢这场比赛。做了一个题不可怕,可怕的是不补题。
也记录一下今天我第一次进入百度之星复赛。
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
2
3 1 1
1 2
8 6 0
1 2
3 1
5 6
4 1
6 4
7 0
Sample Output
2
4
题解:
这个题不是说可以删去最多K条边,然后可以加任意的边。
通过示例一我们知道首先第一步是找入度和出度总和最大的一个顶点,
然后通过这个顶点所在的树来连同其他连通块。
其实这个是答案的一部分,另一部分就是+K,为什么呢,因为可以在其他节点的位置
断开然后连接,所以只要ans=min( ans + k , n - 1 );
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int pre[N],du[N],vis[N],cnt,x,y,n,m,k,root,ans;
int fa(int x){return x==pre[x]?x:pre[x]=fa(pre[x]);}
int main()
{
int T;
scanf("%d",&T);
while(T--){
cnt=0,root=0;
memset(vis,0,sizeof(vis));
memset(du,0,sizeof(du));
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<n;i++){
pre[i]=i;
}
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
du[x]++,du[y]++;
int fx=fa(x),fy=fa(y);
if(fx!=fy){
pre[fx]=fy;
}
}
for(int i=0;i<n;i++){
if(vis[fa(i)]==0){
cnt++;
vis[fa(i)]=1;
}
if(du[root]<du[i]){
root=i;
}
}
ans=du[root]-1+cnt;
ans=min(ans+k,n-1);
printf("%d\n",ans);
}
return 0;
}