zoukankan      html  css  js  c++  java
  • 无向连通图求割边(桥)hdu4738,hdu3849

    点击打开链接

    题目链接:   hdu 4738

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

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

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

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

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

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

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

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

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

    求桥的第一种写法:

     

    #include"string.h"
    #include"stdio.h"
    #include"algorithm"
    #include"iostream"
    #include"stack"
    #define M 1111
    #define inf 999999999
    using namespace std;
    struct st
    {
        int u,v,w,next;
    }edge[M*M*2];
    int head[M],dfn[M],low[M],n,t,index,num;
    int use[M],belong[M];
    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++;
    }
    stack<int>q;
    void tarjan(int u,int id)
    {
        dfn[u]=low[u]=++index;
        q.push(u);
        use[u]=1;
        for(int 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]);
            }
            else if(use[v])
            low[u]=min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u])
        {
            num++;
            int v;
            do
            {
                v=q.top();
                q.pop();
                use[v]=0;
                belong[v]=num;
            }while(u!=v);
        }
    }
    int solve()
    {
        index=num=0;
        int ans=0;
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        for(int i=1;i<=n;i++)
        {
            if(!dfn[i])
            {
                ans++;
                tarjan(i,-1);
            }
        }
        return ans;
    }
    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);
            }
            int msg=solve();
            int mini=inf;
            for(int i=0;i<t;i+=2)
            {
                int u=edge[i].u;
                int v=edge[i].v;
                if(belong[u]!=belong[v])
                    mini=min(mini,edge[i].w);
            }
            if(msg>1)
                printf("0
    ");
            else if(mini>=inf)
                printf("-1
    ");
            else
            {
    
                if(mini==0)
                    printf("1
    ");
                else
                    printf("%d
    ",mini);
            }
        }
    }
    View Code

     

    求桥的第二种写法:

     

    #include"string.h"
    #include"stdio.h"
    #include"iostream"
    #define M 1111
    #define inf 999999999
    using 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
    ");
            else if(num==0)
                printf("-1
    ");
            else
            {
                if(mini==0)
                    printf("1
    ");
                else
                    printf("%d
    ",mini);
            }
        }
    }
    View Code

     

    题目链接:hdu3849

    题目大意:给出一些字符串网络联通图,问有多少个关键路径破坏后使图不连通,若图本身不连通的时候就直接输出0

    程序:

    #include"string.h"  
    #include"stdio.h"  
    #include"iostream"  
    #include"stdlib.h"  
    #define M 10009  
    #define inf 999999999  
    #include"map"  
    #include"string"  
    using namespace std;  
    int cmp(const void *a,const void *b)  
    {  
        return *(int*)a-*(int*)b;  
    }  
    struct st  
    {  
        int u,v,next;  
    }edge[M*30];  
    int head[M],dfn[M],low[M],bridge[M],n,t,index,num,flag;  
    char mp1[M][33];  
    void init()  
    {  
        t=0;  
        memset(head,-1,sizeof(head));  
    }  
    void add(int u,int v)  
    {  
        edge[t].u=u;  
        edge[t].v=v;  
        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;  
            }  
            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 T,m,i;  
        scanf("%d",&T);  
        while(T--)  
        {  
            scanf("%d%d",&n,&m);  
            int k=1;  
            init();  
            map<string,int>mp;  
            while(m--)  
            {  
                char ch1[33],ch2[33];  
                scanf("%s%s",ch1,ch2);  
                if(mp[ch1]==0)  
                    mp[ch1]=k++;  
                if(mp[ch2]==0)  
                    mp[ch2]=k++;  
                int x=mp[ch1];  
                int y=mp[ch2];  
                add(x,y);  
                add(y,x);  
                strcpy(mp1[x],ch1);  
                strcpy(mp1[y],ch2);  
            }  
            solve();  
            if(flag>1)  
            {  
                printf("0
    ");  
                continue;  
            }  
            qsort(bridge,num,sizeof(bridge[0]),cmp);  
            printf("%d
    ",num);  
            for(i=0;i<num;i++)  
            {  
                int j=bridge[i];  
                j=j/2*2;  
                int u=edge[j].u;  
                int v=edge[j].v;  
                printf("%s %s
    ",mp1[u],mp1[v]);  
            }  
        }  
    }  
    View Code

     


  • 相关阅读:
    开网页自动进入路由器设置界面的解决办法(腾达路由器)
    SQL基本语句
    驱动调试配置
    【转】snort
    【转】snort.conf分析(中文)
    【转】snort 笔记2 ----- 规则编写
    【转】Snort语法规则说明及实例讲解
    【转】Snort 命令参数详解
    POST教程笔记
    POST教程笔记
  • 原文地址:https://www.cnblogs.com/mypsq/p/4348260.html
Copyright © 2011-2022 走看看