zoukankan      html  css  js  c++  java
  • luogu题解 P2860[USACO冗余路径Redundant Paths] 缩点+桥

    题目链接

    https://www.luogu.org/problemnew/show/P2860

    https://www.lydsy.com/JudgeOnline/problem.php?id=1718

    分析

    首先这题目的意思就是让任意两点之间至少有两条没有重复道路的路径,很显然,如果这个图不存在桥,就一定满足上述条件。

    于是我们就是要求使这个图不存在桥需要连接的最小边数

    如果把桥从图中去掉,很显然剩余的联通块中任意两点之间至少有两条没有重复道路的路径(当然也可能不是联通块而是孤立的点),对答案不会产生贡献,我们不妨就将这些联通块缩点,于是就原来的图就变成了一颗树。

    然后思考题目要求,当每个节点的度为2时任意两点之间至少有两条没有重复道路的路径,因为此时任意节点都有两条不同道路可走,于是用贪心的思想我们让度数为(1)的先互相连接,所以计算出树中的叶节点个数(x)(lceilfrac{x}{2} ceil)就是答案

    注意

    好象没什么注意的,不过我太菜把(edge [j] .to)写成(edge [i] .to)查了好久的错

    代码

    
        #include <iostream>
        #include <cstdio>
        #include <cstring>
        #include <cstdlib>
        #include <algorithm>
        #include <cctype>
        #include <cmath>
        #include <map>
        #include <queue>
        #define ll long long 
        #define ri register int 
        using namespace std;
        const int maxn=5005;
        const int maxm=10005;
        const int inf=0x7fffffff;
        template <class T>inline void read(T &x){
            x=0;int ne=0;char c;
            while(!isdigit(c=getchar()))ne=c=='-';
            x=c-48;  
            while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
            x=ne?-x:x;
            return ;
        }
        struct Edge{
            int ne,to;
        }edge[maxm<<1];
        int h[maxn],num_edge=0;
        inline void add_edge(int f,int to){
            edge[++num_edge].ne=h[f];
            edge[num_edge].to=to;
            h[f]=num_edge;
            return ;
        }
        int n,m;
        int dfn[maxn],low[maxn],tot=0;
        bool bridge[maxm];
        void tarjan(int now,int in_edge){//所在边的标号
            int v;dfn[now]=low[now]=++tot;
            for(ri i=h[now];i;i=edge[i].ne){
                v=edge[i].to;
                if(!dfn[v]){
                    tarjan(v,i);
                    low[now]=min(low[now],low[v]);
                    if(dfn[now]<low[v]){
                       bridge[i]=bridge[i^1]=true;//是桥
                       bb++;
                    }
                }
                else if(i!=(in_edge^1)){//如果不是在同一条无向边的对应边
                    low[now]=min(low[now],dfn[v]);
                }
            }
            return ;
        }
        int num=0;//联通块的数量
        int in_block[maxn];//各点所在联通块的标号
        bool g[maxn][maxn];//重构后的图(储存)
        void Contraction_Point(int now){//缩点
            int v;in_block[now]=num;
            for(ri i=h[now];i;i=edge[i].ne){
               v=edge[i].to;
               if(!bridge[i]&&!in_block[v]){
                   Contraction_Point(v);
               }
            }
            return ;
        }
        int du[maxn];
        inline void solve(){
            int ans=0,x,y;
            memset(g,0,sizeof(g));
            for(ri i=1;i<=n;i++){
                x=in_block[i];
                for(ri j=h[i];j;j=edge[j].ne){
                    y=in_block[edge[j].to];    //太坑了
                    g[x][y]=g[y][x]=1;
                }
            }
            memset(du,0,sizeof(du));
            for(ri i=1;i<=num;i++){
            	for(ri j=1;j<=num;j++){
            		if(i!=j&&g[i][j]){du[j]++;
        			}
        		}
        	}
            for(ri i=1;i<=num;i++){
                if(du[i]==1)ans++;
            }
            printf("%d",(int)ceil(ans/double(2)));
            return ;
        }
        int main(){
            int x,y;
            read(n),read(m);
            num_edge=1;
            for(ri i=1;i<=m;i++){
                read(x),read(y);
                add_edge(x,y);
                add_edge(y,x);
            }
            memset(bridge,0,sizeof(bridge));
            tarjan(1,0);
            memset(in_block,0,sizeof(in_block));
            for(ri i=1;i<=n;i++){
                if(!in_block[i]){
                    num++;
                    Contraction_Point(i);
                }
            }
            solve();
            return 0;
        }
        
    
  • 相关阅读:
    报错处理
    MySQL8.0跟5.7分组查询表所有字段
    模拟开始时间、结束时间生成历史时间生成曲线模拟数据
    查询电脑登录过的WiFI账号密码
    Samba服务器架设
    CentOS安装GitLab
    申请域名并使用DDNS
    极路由4增强版(极企版)-刷潘多拉固件
    Git命令
    elasticsearch7.6.2 -canal1.1.4集成
  • 原文地址:https://www.cnblogs.com/Rye-Catcher/p/9286688.html
Copyright © 2011-2022 走看看