• poj 3177&&3352 求边双联通分量,先求桥,然后求分量( 临界表代码)


    /*这道题是没有重边的,求加几条边构成双联通,求边联通分量,先求出桥然后缩点,成一个棵树
    找叶子节点的个数*/
    #include<stdio.h>//用容器写在3177这个题上会超内存,但是用临界表过了
    #include<string.h>/*此代码为临界表代码*/
    #define N  5100
    struct node {
    int u,v,next;
    }bian[N*4];
    int dfn[N],low[N],index,f[N*4],n,head[N],yong;
    int Min(int a,int b) {
    return a>b?b:a;
    }
    void addedge(int u,int v) {//建边
    bian[yong].u=u;
    bian[yong].v=v;
    bian[yong].next=head[u];
    head[u]=yong++;
    }
    void tarjan(int u,int pre) {//
     dfn[u]=low[u]=++index;
     int i;
     for(i=head[u];i!=-1;i=bian[i].next) {
        int v=bian[i].v;
        if(i==(pre^1))continue;
        if(!dfn[v]) {
            tarjan(v,i);
            low[u]=Min(low[u],low[v]);//
            if(low[v]>dfn[u])//标记桥
                f[i]=f[i^1]=1;//标记双向的边
        }
        else
            low[u]=Min(low[u],dfn[v]);
     }
    }
    int cnt,c[N];
    void dfs(int u,int fa) {//缩点
    int i;
     c[u]=cnt;//不能放到循环里面,
    for(i=head[u];i!=-1;i=bian[i].next) {
            int v=bian[i].v;
        if(!f[i]&&!c[v]&&i!=(fa^1))//桥不能走,不能回头路,没有被缩过
            dfs(v,i);
    }
    return ;
    }
    int degree[N];
    int slove() {
        int i;
        cnt=1;
        memset(c,0,sizeof(c));
        for(i=1;i<=n;i++)//缩点
                if(!c[i]) {
            dfs(i,-1);
            cnt++;
                }
        memset(degree,0,sizeof(degree));
        for(i=0;i<yong;i++) {
                int u,v;
        u=bian[i].u;
        v=bian[i].v;
                if(c[u]!=c[v]) {//所有边中
                    degree[c[u]]++;
                    degree[c[v]]++;//记录度数
                }
        }
        int leave=0;
        for(i=1;i<cnt;i++) {//度数为一的叶子节点,因为为双向边
            if(degree[i]==2)
                leave++;
        }
        return  (leave+1)/2;
    }
    int main() {
       int m,i,a,b,ans;
       while(scanf("%d%d",&n,&m)!=EOF) {
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(f,0,sizeof(f));
        yong=0;
        memset(head,-1,sizeof(head));
        index=0;
        while(m--){
            scanf("%d%d",&a,&b);
        addedge(a,b);
        addedge(b,a);
        }
        for(i=1;i<=n;i++)
            if(!dfn[i])
            tarjan(i,-1);
            ans=slove();
            printf("%d
    ",ans);
       }
    return 0;
    }
    

  • 相关阅读:
    C#.NET Split 的几种使用方法
    给网站指明手机网网站
    手机访问网站自动跳转到手机版
    手机网页点击链接触发手机自动拨打或保存电话的代码
    图片切换效果2(定时+左右按钮)
    java HttpClient设置代理
    将应用部署到Tomcat根目录的方法
    Java中ArrayList类的用法
    JSP/Serlet 使用fileupload上传文件
    java 格式化字符串
  • 原文地址:https://www.cnblogs.com/thefirstfeeling/p/4410689.html
Copyright © 2020-2023  润新知