题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4738

题意:给定一个n个节点m条边的无向图(可能不连通、有重边),每条边有一个权值。判断其连通性,若双连通,输出-1;若非连通,输出0;否则,输出权值最小的桥的权值。

思路:进行双连通域分解,记下连通块的个数和所有桥的情况,对应输出结果即可。

注意对重边的处理。这里我按照上一道题学到的姿势如法炮制:先把所有边按“字典序”排序(u, v, w),这样重边聚集在一起了,然后扫描一遍,发现重边即在结构体Edge中打重边标记;由于重边一定不是桥,因此选哪个的权值实际上无所谓。

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define CLEAR(A, X) memset(A, X, sizeof(A))
#define REP(N) for(int i=0; i<(N); i++)
#define REPE(N) for(int i=1; i<=(N); i++)
#define FREAD(FN) freopen((FN), "r", stdin)
#define pb(a) push_back(a) using namespace std; const int MAX_N = ;
const int MAX_M = ;
const int INF = ;
int n, m; struct Edge
{
int v, next;
int w;
bool isBrg;
bool isDup;
}edges[MAX_M];
int numE;
int head[MAX_N];
int low[MAX_N], dfn[MAX_N], clock;
int inStack[MAX_N], S[MAX_N], topS;
int block, belong[MAX_N];
int numBrg;
int cnt;//连通块个数 void init(){
numE = ;
clock = block = topS = ;
numBrg = ;
CLEAR(low, );
CLEAR(dfn, );
CLEAR(head, -);
CLEAR(belong, );
CLEAR(inStack, );
} void addEdge(int u, int v, int w, bool isDup){
edges[numE].v = v;
edges[numE].w = w;
edges[numE].isBrg = ;
edges[numE].isDup = isDup;
edges[numE].next = head[u];
head[u] = numE++; //反向边
edges[numE].v = u;
edges[numE].w = w;
edges[numE].isBrg = ; //这里之前忘清零了,一直WA。。。
edges[numE].isDup = isDup;
edges[numE].next = head[v];
head[v] = numE++;
} void bcc(int u, int p, int isDup){
low[u] = dfn[u] = ++clock;
S[topS++] = u;
inStack[u] = ;
for(int i=head[u]; i != -; i = edges[i].next){
int v = edges[i].v;
if(v == p && (!isDup)) continue;
if(!dfn[v]){
bcc(v, u, edges[i].isDup);
low[u] = min(low[u], low[v]);
if(low[v] > dfn[u]){//bridge
numBrg++;
edges[i].isBrg = ;
edges[i^].isBrg = ;
}
}else if(inStack[v]){//backward
low[u] = min(low[u], dfn[v]);
}
}
if(low[u] == dfn[u]){//new bcc
block++;
int t;
do{
t = S[--topS];
inStack[t] = ;
belong[t] = block;
}while(t != u);
}
} struct Node
{
int u, v, w;
Node(){}
Node(int uu, int vv, int ww):u(uu), v(vv), w(ww){}
}nodes[MAX_M];
bool cmp(Node a, Node b){
if(a.u == b.u){
if(a.v == b.v) return a.w < b.w;
return a.v < b.v;
}
return a.u < b.u;
}
bool same(Node a, Node b){
return a.u == b.u && a.v == b.v;
} int main()
{
FREAD("4738.txt");
while(~scanf("%d%d", &n, &m) && !(n== && m==)){
init();
REP(m){
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
if(u > v) swap(u, v);//保持顺序
nodes[i] = Node(u, v, w);
}
sort(nodes, nodes+m, cmp);
int cur = , i = ;
int flagDup = ;
while(cur < m){
while(i < m && same(nodes[cur], nodes[i])){
flagDup = ;
i++;
}//重边一定不是桥,
if(flagDup) addEdge(nodes[cur].u, nodes[cur].v, nodes[cur].w, true);
else addEdge(nodes[cur].u, nodes[cur].v, nodes[cur].w, false);
flagDup = ;
cur = i++;
}
cnt = ;
REPE(n){
if(!dfn[i]){
bcc(i, , );
cnt++;
}
}
int ans = INF;
if(cnt > ) ans = ;//非连通
else if(cnt== && !numBrg) ans = -;//边双连通
else{//有桥
// REPE(n){
// for(int j=head[i]; j != -1; j = edges[j].next){
// int v = edges[j].v;
// if(belong[i] != belong[v])
// ans = min(ans, edges[j].w);
// }
// }
REPE(numE){
if(edges[i].isBrg)
ans = min(ans, edges[i].w);
}
if(ans == ) ans = ;//至少派一人
}
printf("%d\n", ans);
}
return ;
}

判桥用 edges[i].isBrg 或 belong[u] == belong[v]都可以,二者等价。

多组样例,我开始用第一种但忘记在addEdge中把isBrg清零了才会WA。

【HDU 4738 Caocao's Bridges】BCC 找桥的更多相关文章

  1. HDU 4738 Caocao's Bridges ——(找桥,求联通块)

    题意:给你一个无向图,给你一个炸弹去炸掉一条边,使得整个图不再联通,你需要派人去安置炸弹,且派去的人至少要比这条边上的人多.问至少要派去多少个,如果没法完成,就输出-1. 分析:如果这个图是已经是多个 ...

  2. Hdu 4738 Caocao's Bridges (连通图+桥)

    题目链接: Hdu 4738 Caocao's Bridges 题目描述: 有n个岛屿,m个桥,问是否可以去掉一个花费最小的桥,使得岛屿边的不连通? 解题思路: 去掉一个边使得岛屿不连通,那么去掉的这 ...

  3. hdu 4738 Caocao's Bridges (tarjan求桥)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4738 题目大意:给一些点,用一些边把这些点相连,每一条边上有一个权值.现在要你破坏任意一个边(要付出相 ...

  4. HDU 4738 Caocao's Bridges(Tarjan求桥+重边判断)

    Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  5. HDU 4738——Caocao's Bridges——————【求割边/桥的最小权值】

     Caocao's Bridges Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u S ...

  6. HDU 4738 Caocao's Bridges (2013杭州网络赛1001题,连通图,求桥)

    Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  7. hdu 4738 Caocao's Bridges 图--桥的判断模板

    Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  8. HDU——4738 Caocao's Bridges

    Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  9. HDU 4738 Caocao's Bridges

    Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

随机推荐

  1. x2engine

    x2engine 各版本下载 https://bitnami.com/stack/x2crm/installer https://bitnami.com/redirect/to/36211/bitna ...

  2. 基于PCA和SVM的人脸识别

    程序中采用的数据集是ORL人脸库,该人脸库共有400副人脸图像,40人,每人10幅,大小为112*92像素,同一个人的表情,姿势有少许变化. 程序的流程主要分为三部分,数据的预处理(PCA降维和规格化 ...

  3. 执行testng appium用例失败,自动截图

    新建一个截图监听类ScreenShotListener ,重写onTestFailure方法,里面定义了 监听的driver ,截图文件路径和名称 package com.fsssc.htsgl.ut ...

  4. 获取某个文件夹中所有txt文件

    <?php // 获取文件夹中的所有txt文件名 $dir = "D:/a"; //这里输入其他路径 $handle = opendir($dir."." ...

  5. Android : 如何在WebView显示的页面中查找内容

    Android : 如何在WebView显示的页面中查找内容 Author : Aoyousatuo Zhao http://blog.sina.com.cn/aoyousatuo WebView是A ...

  6. 新建的硬盘-mount

    一.查看已经格式化或已挂接硬盘 df -aT 等命令(自己度娘) 二.查看未挂硬盘和未格式化硬盘 1.fdisk -l 比如/dev/sdb  如果已经分区,会有sdb1. 2.格式化 #mkfs - ...

  7. javascript解决for循环中i取值的问题(转载)

    html: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...

  8. Canvas简单动画和像素处理

    动画 利用JavaScript,可以在canvas元素上很容易地产生动画效果. var posX = 20, posY = 100; setInterval(function() { context. ...

  9. FileShare文件读写锁解决“文件XXX正由另一进程使用,因此该进程无法访问此文件”(转)

    开发过程中,我们往往需要大量与文件交互,读文件,写文件已成家常便饭,本地运行完美,但一上到投产环境,往往会出现很多令人措手不及的意外,或开发中的烦恼,因此,我对普通的C#文件操作做了一次总结,问题大部 ...

  10. (转)union和union all的区别

    Union因为要进行重复值扫描,所以效率低.如果合并没有刻意要删除重复行,那么就使用Union All 两个要联合的SQL语句 字段个数必须一样,而且字段类型要“相容”(一致): 如果我们需要将两个s ...