您的位置:首页 > 其它

hdu 4612 求边连通分量+求树的直径

2016-05-07 18:35 337 查看
http://acm.hdu.edu.cn/showproblem.php?pid=4612

题意:

加一条边,使得桥的数量最少?

思路:

求边连通分量,缩点,然后变成一个树,树边都是桥,求树的直径。

树的直径就是最多减少的桥。

桥的数量最少就是原图中的桥的数量 - 树的直径。

要注意重边。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
using namespace std;
typedef pair<int,int> pii;
const int M_node = 200009, M_edge = 2000009;
int low[M_node],dfn[M_node],belong[M_node],head[M_node];
int dfs_clock,block,bridge,tot;
int n,m,maxlen,s;
bool instack[M_node];
struct Node
{
int u,v;
}node[M_edge];
struct edge
{
int to,next;
bool cut;
bool mul;
}edge[M_edge];
vector<int> G[M_node];
stack<int> st;
void init()
{
memset(head,-1,sizeof(head));
dfs_clock = block = bridge = tot = 0;
}
void add_edge(int u,int v,bool mul)
{
edge[tot].to = v;
edge[tot].next = head[u];
edge[tot].cut = false;
edge[tot].mul = mul;
head[u] = tot++;
}
void tarjan(int u,int fa,bool mul)
{
low[u] = dfn[u] = ++dfs_clock;
st.push(u);
instack[u] = true;
for(int i = head[u]; i != -1;i = edge[i].next)
{
int v = edge[i].to;
if(v == fa && !mul) continue; //如果不是重边才跳过
if(!dfn[v])
{
tarjan(v,u,edge[i].mul);
low[u] = min(low[v],low[u]);
if(low[v] > dfn[u])
{
bridge++;
edge[i].cut = true;
edge[i^1].cut = true;
}
}
else if(instack[u] && low[u] > dfn[v]) low[u] = dfn[v];
}
if(low[u] == dfn[u])
{
block++;
for(;;)
{
int v = st.top();
st.pop();
instack[v] = false;
belong[v] = block;
if(v == u) break;
}
}
}
void dfs(int u,int pre,int len)
{
if(maxlen < len)
{
s = u;
maxlen = len;
}
for(int i = 0; i < G[u].size();i++)
{
int v = G[u][i];
if(v == pre) continue;
dfs(v,u,len+1);
}
}
void solve()
{
while(!st.empty()) st.pop();
memset(dfn,0,sizeof(dfn));
memset(instack,false,sizeof(instack));
tarjan(1,-1,false);
for(int i = 1;i <= block;i++) G[i].clear();
for(int i = 1;i <= n;i++)
{
for(int j = head[i];j != -1;j = edge[j].next)
{
if(edge[j].cut)
{
//printf("debug -- i = %d , belong[i] = %d , edge[j].to = %d , belong[edge[j].to] = %d\n",i,belong[i],edge[j].to,belong[edge[j].to]);
G[belong[i]].push_back(belong[edge[j].to]);
}
}
}
maxlen = -1;
dfs(1,-1,0);
maxlen = -1;
dfs(s,-1,0);
printf("%d\n",bridge - maxlen);
}
bool cmp(Node a,Node b)
{
if(a.u == b.u) return a.v < b.v;
return a.u < b.u;
}
int main()
{
while(scanf("%d %d",&n,&m) == 2)
{
init();
if(n == 0 && m == 0) break;
for(int i = 0;i < m;i++)
{
int a,b;
scanf("%d %d",&a,&b);
if(a == b) continue;
if(a > b) swap(a,b);
node[i].u = a;
node[i].v = b;
}
sort(node,node+m,cmp);
for(int i = 0;i < m;i++)
{
if(i == 0 || (node[i].u != node[i-1].u || node[i].v != node[i-1].v))
{
if(i < m - 1 && node[i].u == node[i+1].u && node[i].v == node[i+1].v)
{
add_edge(node[i].u,node[i].v,true);
add_edge(node[i].v,node[i].u,true);
}
else
{
add_edge(node[i].u,node[i].v,false);
add_edge(node[i].v,node[i].u,false);
}
}
}
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: