HDU 3394 Railway(点双连通分量+桥)
http://acm.hdu.edu.cn/showproblem.php?pid=3394
题意:一个无向图(可能不连通)有n个点和m条边.现在要你找出冲突边和多余边的数目.其中冲突边是那些同时存在于多个环中的边,而多余边是不在任何一个环中的边.
分析:
首先我们可以知道多余边就是该无向图中的桥,桥必然不在任何环中.冲突边只能在点双连通分量中,而什么样的点双连通分量有冲突边呢?
对于有n个节点和n条边(或小于n条边,比如2点1边)的点双连通分量,这种分量只有一个大环,不存在其他任何环了,所以这种分量中的边都不是冲突边.
对于有n个节点和m条边(m>n)的点双连通分量来说,该分量内的所有边都是冲突边.因为边数>点数,所以该分量必有至少两个环,我们随便画个图就可知其中的任意边都至少在两个以上的环上.
综上所述,对于多余边,我们输出桥数.对于冲突边,我们输出边数>点数的点双连通分量的所有边数.
AC代码:
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
const int maxn=10000+10;
int n,m;
int ans1,ans2;//多余边,冲突边
vector<int> G[maxn];
int dfs_clock,bcc_cnt;
int pre[maxn],low[maxn],bcc[maxn],bccno[maxn];
struct Edge
{
int u,v;
Edge(int u,int v):u(u),v(v){}
};
stack<Edge> S;
void solve()
{
bool vis[maxn];
int sum=0;
memset(vis,0,sizeof(vis));
for(int i=1;i<=bcc[0];i++) vis[bcc[i]]=true;
for(int i=1;i<=bcc[0];i++)
{
int u=bcc[i];
for(int j=0;j<G[u].size();j++)
if(vis[G[u][j]]) sum++;
}
sum /=2;
if(sum>bcc[0]) ans2+= sum;
}
void tarjan(int u,int fa)
{
low[u]=pre[u]=++dfs_clock;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(v==fa) continue;
Edge e=Edge(u,v);
if(!pre[v])
{
S.push(e);
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=pre[u])//u是割点
{
if(low[v]>pre[u]) ans1++;
bcc_cnt++;
bcc[0]=0;
while(true)
{
Edge x=S.top(); S.pop();
if(bccno[x.u]!=bcc_cnt)
{
bcc[++bcc[0]]=x.u, bccno[x.u]=bcc_cnt;
}
if(bccno[x.v]!=bcc_cnt)
{
bcc[++bcc[0]]=x.v, bccno[x.v]=bcc_cnt;
}
if(x.u==u && x.v==v) break;
}
solve();
}
}
else if(pre[v]< pre[u])
{
S.push(e);
low[u]=min(pre[v],low[u]);
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)==2&&n)
{
ans1=ans2=bcc_cnt=dfs_clock=0;
memset(pre,0,sizeof(pre));
memset(bccno,0,sizeof(bccno));
for(int i=0;i<n;i++) G[i].clear();
while(m--)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
for(int i=0;i<n;i++)
if(!pre[i]) tarjan(i,-1);
printf("%d %d\n",ans1,ans2);
}
return 0;
}
分享到:
相关推荐
hdu 1695 GCD(欧拉函数+容斥原理).docx
acm hdu as easy as a+b
ACM题库,一些题目和答案,以及解题报告,传上来共享
本人准备2020年保研机试时刷的题目(虽然最后机试取消了,...来自某中流985,在HDU和vjudge平台上大概刷了400道。本文件地图(excel表格)包含了绝大部分我刷过的题目,笔记中具有思路、代码、总结和心得。 大佬勿入!
杭电OnlineJudge 200-2099的解题报告
求一个有向图n个点 m 条边,是否是强连通分量,如果是输出Yes, 不是输出No. 数据范围 n < 10000, m < 100000 思路: Tarjan模板题 补习: AC code: /* Tarjan求有向图的强连通分量, */ #include #...
HDU的1250,主要是利用高精度加法,但是代码有点繁琐,效率不是很高
300+ AC 代码 。 大数 , 线段树 , 字符串 , dp.....
杭电ACMhdu1163
HDU1059的代码
hdu1001解题报告
hdu 1574 passed sorce
HDU的一题........HDU DP动态规
hdu2101AC代码
hdu acm 教案 搜索入门 hdu acm 教案 搜索入门
hdu 3341(ac自动机+状态压缩) 题意:容易理解... 思路:首先一开始容易想到要用到dp,开设一个dp[41][41][41][41][501]的数组来解决,但是明显内存已经超出范围了,于是就想如何减少内存呢?只要知道A、T、C、G其中...
搜索 dfs 解题代码 hdu1241
hdu 5007 Post Robot 字符串枚举。 暴力一下就可以了。
hdu acm 教案 动态规划(1) hdu acm 教案 动态规划(1)
hdu 1166线段树代码