题目链接: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. c语言二维数组变色龙之死字的打印

    1 #include <stdio.h> #include <stdlib.h> void main() { ][]= { {'#','#','#',' ','#','#',' ...

  2. lucene3.6.0 经典案例 入门教程

    第一步:下载并导入lucene的核心包(注意版本问题):  例如Lucene3.6版本:将lucene-core-3.6.0.jar拷贝到项目的libs 文件夹里.  例如Lucene4.6版本:将l ...

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

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

  4. vagrant拷贝后vagrant file需要加的配置

    config.ssh.forward_agent config.ssh.username = "vagrant" config.ssh.password = "vagra ...

  5. Django之Cookie与Session

    一.cookie 1.cookie使用 def cookie(request): print(request.COOKIES) # 获取所有的COOKIES obj = render(request, ...

  6. web工程调用hadoop集群1.2

    本实例代码在lz的资源中有上传,有需要的可以参考(下载后的文件解压后有两个,一个直接导入myeclipse工程,另外的jar放在hadoop的lib下面,只需修改Utils中的ip即可运行该程序): ...

  7. 【Nginx】事件和连接

    不同的操作系统相应不同的事件驱动机制.在Linux 2.6之后使用epoll机制.相应的事件驱动模块是ngx_epoll_module.Nginx的ngx_event_core_module模块依据操 ...

  8. Jquery:Jquery中的事件<一>

    由于今天有一个比较重要的面试,所以昨天晚上对以前做的一些项目做了一下总结,直接导致昨天的学习笔记断更了,哎,计划永远赶不上变化啊!今天学习了Jquery中是事件,就此做一个笔记,便于日后复习. 一.加 ...

  9. linux下mysql环境支持中文配置步骤

    sql脚本执行前加上: CREATE DATABASE IF NOT EXISTS mydatabase DEFAULT CHARSET utf8 COLLATE UTF8_GENERAL_CI; u ...

  10. Oracle System密码忘记 密码修改、删除账号锁定lock

    一下转自http://www.cnblogs.com/yjhrem/articles/2340149.html 运行cmd命令行 录入 sqlplus /nolog  无用户名登录 conn /as ...