[HDU 4738] Caocao's Bridges Tarjan算法求桥

题目传送门:【HDU 4738】


题目大意: 多组数据。给出一个含有 n 个点和 m 条边的无向图(1 ≤ n ≤ 1000,1 ≤ m ≤ n 2 ),现在,你要找出一条边,使得删除这条边之后,整个图变得不连通;找出满足的边里权值最小的那条边并输出结果,找不到则输出 -1。输入为两个 0 时结束。


题目分析:

模板题。题目大意已经十分明确,直接使用 Tarjan 算法求桥,然后维护最小权值即可。
具体操作为

void tarjan(int u,int fa)  // fa代表之前走过来的边的编号

注意,本题要结合以下条件:每条边即使没人,也要派至少一个人去执行任务(题意说了的);如果一开始就是不连通的图,那么就不用派人去执行任务了,输出 0。(题意也说了的)

下面附上代码:

  1. #include<cstdio>  
  2. #include<cstring>  
  3. #include<algorithm>  
  4. using namespace std;  
  5. typedef long long LL;  
  6. const int MX=1005;  
  7. const int INF=0x3f3f3f3f;  
  8.   
  9. struct Edge{  
  10.     int to,next,num;  
  11. }edge[MX*MX*2];  
  12. int n,m,head[MX],now=1;                                     //now设为1,方便之后异或   
  13. int dfn[MX],low[MX],_index=0,mind=INF;  
  14. bool vis[MX*MX*2];  
  15.   
  16. inline void adde(int u,int v,int w){  
  17.     edge[++now].to=v;  
  18.     edge[now].num=w;  
  19.     edge[now].next=head[u];  
  20.     head[u]=now;  
  21. }  
  22. void tarjan(int u,int fa){                                  //这里的 fa 表示的是上一条边   
  23.     dfn[u]=low[u]=++_index;  
  24.     int child=0;  
  25.     for (int i=head[u];i;i=edge[i].next){  
  26.         int v=edge[i].to;  
  27.         if (!dfn[v]){  
  28.             child++;  
  29.             tarjan(v,i);  
  30.             if (low[v]<low[u]){  
  31.                 low[u]=low[v];  
  32.             }  
  33.             if (low[v]>dfn[u]){  
  34.                 if (edge[i].num<mind)  
  35.                     mind=edge[i].num;  
  36.             }  
  37.         } else if (dfn[v]<low[u] && fa!=(i^1)){              //求桥不能直接返回到u点   
  38.             low[u]=dfn[v];  
  39.         }  
  40.     }  
  41. }  
  42. void _init(){  
  43.     memset(dfn,0,sizeof(dfn));  
  44.     memset(head,0,sizeof(head));  
  45.     now=1,_index=0,mind=INF;  
  46. }  
  47.   
  48. int main(){  
  49.     while (scanf(“%d%d”,&n,&m) && (n || m)){  
  50.         int a,b,w;  
  51.         for (int i=1;i<=m;i++){  
  52.             scanf(”%d%d%d”,&a,&b,&w);  
  53.             adde(a,b,w);  
  54.             adde(b,a,w);  
  55.         }  
  56.         tarjan(1,-1);  
  57.         for (int i=1;i<=n;i++)  
  58.             if (!dfn[i]){  
  59.                 mind=-1;  
  60.                 break;  
  61.             }  
  62.           
  63.         if (mind==-1) printf(“0\n”);                            //图不连通   
  64.         else if (mind<INF) printf(“%d\n”,mind>0?mind:1);      //至少需要 1 个人   
  65.         else printf(“-1\n”);                                    //不存在桥   
  66.         _init();  
  67.     }  
  68.     return 0;  
  69. }  
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值