今天做题的时候,提交的代码 内存超限了,以前没怎么遇到过这种情况。本人刚开始学习此类知识,最近刚开始刷题,请大家指点。
题目 HDU-4612
(https://acm.hdu.edu.cn/showproblem.php?pid=4612)
#include<iostream>
#include<map>
#include<vector>
#include<cstring>
#include<queue>
using namespace std;
vector<int> Map[200001];//原图
vector<int> edge[200001];//缩点图
map<pair<int,int>,bool> bridge;//记录桥
int ans[200001];//记录边双联通分量
int dfn[200001];//时间戳
int low[200001];//回溯值
bool flag[200001];//标记
int cnt=0,cntb=0,D=0;
int d[200001];//表示路径的长度
int n,m;
void tarjan(int u,int f)// tarjan 求出桥,用bridge记录桥的两个端点
{
cnt++;
dfn[u]=cnt;
low[u]=cnt;
for(int i=0;i<Map[u].size();i++)
{
int v=Map[u][i];
if(!dfn[v])
{
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u])
{
bridge[{u,v}]=bridge[{v,u}]=1;
}
}
else if(f!=v)//不考虑 子-->父 的情况
low[u]=min(low[u],dfn[v]);
}
}
void dfs(int u)//dfs根据桥找出边双连通分量
{
ans[u]=cntb;
for(int i=0;i<Map[u].size();i++)
{
int v=Map[u][i];
if(ans[v]||bridge[{u,v}])
continue;
dfs(v);
}
}
void dp(int u) {//求树的直径
flag[u] = true;
for (int j = 0; j < edge[u].size(); j ++)
{
int v = edge[u][j];
if (flag[v])
continue;
dp(v);
D = max(D, d[u] + d[v] + 1);
d[u] = max(d[u], d[v] + 1);
}
}
int main(void)
{
while(cin>>n>>m)
{
if(n==0&&m==0)
break;
for(int i=1;i<=m;i++)//输入边的端点
{
int u,v;
cin>>u>>v;
Map[u].push_back(v);
Map[v].push_back(u);
}
for(int i=1;i<=n;i++)//tarjan 调用
if(!dfn[i])
tarjan(i,0);
for(int i=1;i<=n;i++) // dfs调用
if(!ans[i])
{cntb++;dfs(i);}
int count=0;
for(int i=1;i<=n;i++)// 依据边双连通分量来建立缩点图
{
for(int j=0;j<Map[i].size();j++)
{
int v=Map[i][j];
if(ans[i]!=ans[v])
{
count++;
edge[ans[i]].push_back(ans[v]);
}
}
}
dp(1);
// cout<<count/2<<" "<<D<<endl;
cout<<count/2-D<<endl;// 桥的数量 - 树的直径 就是答案
}
}
上网查了一下,网上没有针对性的解答,不知道哪里有问题
希望大家能指点出错误或提出一些建议