无向连通图求割边(桥)hdu4738

来源:互联网 发布:php二维数组去除重复 编辑:程序博客网 时间:2024/05/06 11:48

点击打开链接

题目链接:   hdu 4738

题目大意:   曹操有N个岛,这些岛用M座桥连接起来

                  每座桥有士兵把守(也可能没有)

                  周瑜想让这N个岛不连通,但只能炸掉一座桥

                  并且炸掉一座桥需要派出不小于守桥士兵数的人去

解题思路:   首先判断图是否连通,不连通则不需要去炸桥,输出0

                  图连通,则可以用Tarjan找割边

                  割边不存在输出-1表示不能达到目的

                  找到所有的割边,只需要炸掉其中守兵数最少的桥即可

                  PS: 桥的守兵数为0时,也需要派出一个人去炸桥!

#include"string.h"#include"stdio.h"#include"iostream"#define M 1111#define inf 999999999using namespace std;struct st{    int u,v,w,next;}edge[M*M*2];int head[M],dfn[M],low[M],bridge[M],n,t,index,num,mini,flag;void init(){    t=0;    memset(head,-1,sizeof(head));}void add(int u,int v,int w){    edge[t].u=u;    edge[t].v=v;    edge[t].w=w;    edge[t].next=head[u];    head[u]=t++;}void tarjan(int u,int id){    dfn[u]=low[u]=++index;    int i;    for(i=head[u];i!=-1;i=edge[i].next)    {        if(i==(1^id))continue;        int v=edge[i].v;        if(!dfn[v])        {            tarjan(v,i);            low[u]=min(low[u],low[v]);            if(low[v]>dfn[u])            {                bridge[num++]=i;                if(mini>edge[i].w)                    mini=edge[i].w;            }        }        low[u]=min(low[u],dfn[v]);    }}void solve(){    index=num=flag=0;    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    for(int i=1;i<=n;i++)    {        if(!dfn[i])        {            flag++;            tarjan(i,-1);        }    }}int main(){    int m;    while(scanf("%d%d",&n,&m),m||n)    {        init();        while(m--)        {            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            add(a,b,c);            add(b,a,c);        }        mini=inf;        solve();        if(flag>1)            printf("0\n");        else if(num==0)            printf("-1\n");        else        {            if(mini==0)                printf("1\n");            else                printf("%d\n",mini);        }    }}


0 0
原创粉丝点击