标签:实现 解决 tle inf tor 注意 必须 lse with
首先有一个性质,删一条边最多能使连通块的个数+1
之后考虑哪些边能使连通块的个数+1
很明显是非环边
为什么不能是环呢?
对于一个环如果只删一条边,只会使这个环变成一条链
之后我们先将所有的非环边删去
再对每一个环按照环的大小进行从大到小进行排序,
为什么要从大到小呢?
对于每一个环,
首先必须删一条边,在删完这条边之后的删的边才能是连通块的个数+1
也就是说破环成链的次数越少越好。
以上就是大体的思路
实现的难(♂)点就是如何判断环边与非环边
其实用一次DFS就可以解决,我们对每一个遍历到的点定义一个dep
如果在遍历u号的儿子v节点时
发现\(dep_u>dep_v且dep_u-dep_v>1\)的话就可以确定一个环的大小
注意一定不能用不关同步的cin和cout
不然:\(TLE*\infty\)
笔者以为是自己代码本身的问题,耗了一个上午,WTF!!!
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int n,m,k;
int tot_cir;
int ans;
int depth[1000005];
vector<int> cir;
vector<int> g[1000005];
void dfs(int u,int fr)
{
depth[u]=depth[fr]+1;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(depth[v]==0)
{
dfs(v,u);
}
else if(depth[v]<depth[u])
{
if(depth[u]-depth[v]>1)
{
cir.push_back(depth[u]-depth[v]+1);
tot_cir+=depth[u]-depth[v]+1;
}
}
}
}
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m>>k;
for(int i=1;i<=m;i++)
{
int u;
int v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
for(int i=1;i<=n;i++)
{
if(!depth[i])
{
ans++;
dfs(i,0);
}
}
if(k-(m-tot_cir)<=0)
{
cout<<k+ans;
return 0;
}
else
{
k-=(m-tot_cir);
ans+=(m-tot_cir);
sort(cir.begin(),cir.end(),cmp);
for(int i=0;i<cir.size()&&k;i++)
{
if(k>=cir[i])
{
ans+=cir[i]-1;
k-=cir[i];
}
else
{
ans+=k-1;
break;
}
}
}
cout<<ans;
return 0;
}
标签:实现 解决 tle inf tor 注意 必须 lse with
原文地址:https://www.cnblogs.com/loney-s/p/11782803.html