您的位置:首页 > 其它

HDU 4738 双连通分量 Caocao's Bridges

2015-08-12 09:32 239 查看
求权值最小的桥,考虑几种特殊情况:

图本身不连通,那么就不用派人去了

图的边双连通分量只有一个,答案是-1

桥的最小权值是0,但是也要派一个人过去

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
using namespace std;

const int maxn = 1000 + 10;
const int maxm = 1000000 + 10;

int n, m;

int cc;
int pa[maxn];
int findset(int x) { return x == pa[x] ? x : pa[x] = findset(pa[x]); }

void Union(int x, int y)
{
int px = findset(x), py = findset(y);
if(px != py) { pa[px] = py; cc--; }
}

struct Edge
{
int v, nxt, w;
}edges[maxm * 2];
int ecnt;
int head[maxn];

void AddEdge(int u, int v, int d)
{
edges[ecnt].v = v;
edges[ecnt].w = d;
edges[ecnt].nxt = head[u];
head[u] = ecnt++;
}

stack<int> S;
bool isbridge[maxm * 2];
int dfs_clock, scc_cnt;
int low[maxn], pre[maxn], sccno[maxn];

void dfs(int u, int fa)
{
pre[u] = low[u] = ++dfs_clock;
S.push(u);

for(int i = head[u]; ~i; i = edges[i].nxt)
{
if(i == (fa ^ 1)) continue;
int v = edges[i].v;
if(!pre[v])
{
dfs(v, i);
low[u] = min(low[u], low[v]);
if(low[v] > low[u]) isbridge[i] = true;
}
else if(!sccno[v]) low[u] = min(low[u], pre[v]);
}

if(low[u] == pre[u])
{
scc_cnt++;
for(;;)
{
int x = S.top(); S.pop();
sccno[x] = scc_cnt;
if(x == u) break;
}
}
}

void find_scc()
{
dfs_clock = scc_cnt = 0;
memset(isbridge, false, sizeof(isbridge));
memset(pre, 0, sizeof(pre));
memset(sccno, 0, sizeof(sccno));
for(int i = 1; i <= n; i++) if(!pre[i]) dfs(i, -1);
}

int main()
{
while(scanf("%d%d", &n, &m) == 2 && n)
{
ecnt = 0;
memset(head, -1, sizeof(head));
cc = n;
for(int i = 1; i <= n; i++) pa[i] = i;
while(m--)
{
int u, v, d; scanf("%d%d%d", &u, &v, &d);
Union(u, v);
AddEdge(u, v, d); AddEdge(v, u, d);
}

if(cc > 1) { puts("0"); continue; }

find_scc();

if(scc_cnt == 1) { puts("-1"); continue; }

int ans = 1000000000;
for(int i = 0; i < ecnt; i += 2) if(isbridge[i]) ans = min(ans, edges[i].w);
if(!ans) ans = 1;
printf("%d\n", ans);
}

return 0;
}


代码君
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: