您的位置:首页 > 其它

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

2013-09-15 22:46 323 查看
题意:

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

题解:

总的来说..用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 3000005
using 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: