HDOJ 4738 - Caocao's Bridges 用tarjan找无向图的桥..注意trick

来源:互联网 发布:游乃海 知乎 编辑:程序博客网 时间:2024/05/16 13:49

              题意:

                       赤壁之战,曹操把所有的船都用桥连起来了...如果船都是联通的..则曹操是必胜的..而现在周瑜可以用一个炸弹炸掉一个桥..若能让曹操的所有船不联通..则可以逆转局势获得胜利..但是要炸某个桥..就必须派出一些士兵去执行..现在告诉有哪些桥.在哪两点间.并且炸掉这个桥所需要的士兵数量..问周瑜能否逆转局势,并且所需要的兵力最少是多少..

              题解:

                       总的来说..用tarjan求出桥..然后找到所需士兵最小的桥就是答案了..但要注意两个情况:

                      1、图是不联通的..那么不需要炸桥了..代价为0

                      2、要炸毁桥..必须派出兵力..也就是说当最小的桥所需兵力为0时..答案也是1..因为根据提议.需要一个人来背炸药的...


Program:

#include<iostream>#include<stack>#include<queue>#include<stdio.h>#include<algorithm>#include<string.h>#include<cmath>#define ll long long#define oo 1000000007#define eps 1e-5#define MAXN 3005#define MAXM 3000005using namespace std;   struct node{      int x,y,l,id,next;}edge[MAXM];int  Lnum,_next[MAXN],dfn[MAXN],low[MAXN],DfsIndex,father[MAXN];bool brige[MAXM];void addedge(int x,int y,int l,int id){       edge[++Lnum].next=_next[x],_next[x]=Lnum;       edge[Lnum].x=x,edge[Lnum].y=y,edge[Lnum].l=l,edge[Lnum].id=id;       swap(x,y);       edge[++Lnum].next=_next[x],_next[x]=Lnum;       edge[Lnum].x=x,edge[Lnum].y=y,edge[Lnum].l=l,edge[Lnum].id=id;}void tarjan(int x,int id)  {         int y,k;         dfn[x]=low[x]=++DfsIndex;         for (k=_next[x];k;k=edge[k].next)         {                  if (edge[k].id==id) continue;                 y=edge[k].y;                 if (!dfn[y])                 {                     tarjan(y,edge[k].id);                     low[x]=min(low[x],low[y]);                     if (dfn[x]<low[y]) brige[k]=true;                 }else                     low[x]=min(low[x],dfn[y]);         }                return;  }  int getfather(int x){      if (father[x]==x) return x;      return father[x]=getfather(father[x]);}int main(){       int n,m,x,y,i,l,ans;       while (~scanf("%d%d",&n,&m) && n)      {                Lnum=0,memset(_next,0,sizeof(_next));                for (i=1;i<=n;i++) father[i]=i;                for (i=1;i<=m;i++)                 {                        scanf("%d%d%d",&x,&y,&l);                        if (!l) l=1;                        addedge(x,y,l,i);                        father[getfather(x)]=getfather(y);                }                for (i=2;i<=n;i++)                   if (getfather(i)!=getfather(1)) break;                if (i<=n)                {                        printf("0\n");                        continue;                }                memset(brige,false,sizeof(brige));                memset(dfn,false,sizeof(dfn)),DfsIndex=0;                ans=oo;                tarjan(1,0);                for (i=1;i<=Lnum;i++)                   if (brige[i]) ans=min(ans,edge[i].l);                if (ans==oo) printf("-1\n");                       else  printf("%d\n",ans);      }      return 0;}


原创粉丝点击