• 1454E Number of Simple Paths


    题目传送门

    经典没读懂题瞎推一波样例求不出来安详入睡

    题意

      无向图,n个点,n个边,求图中任意一个点到另一个点的不重复路径总数。拿下图举例:

    【1,2,3,4】和【1,2,4,3】是不重复的两条路径。而【1,2,3,4】和【4,3,2,1】重复了。

    n个点的树有n-1条边,若再加一条边,则会形成一个环,除了环之外,其余部分由若干子树构成。  ==>   基环树。

    对于无向图,拓扑排序处理出环,再处理出环上每个节点分支上的的节点个数。

    设 ans=n*(n-1)  ,这是所有节点都在环上的情况,每个节点到另一个节点有两条路径。

    如果环上某个节点分支上有若干个节点,那么这个分支上的路径数实际是重复的,设 cnt 为环上某个节点分支上的节点总数,则重复路径数为 C2cnt  ,asn 减去重复路径数即为总路径数。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int inf =0x3f3f3f3f;
     5 const int qs=2e5+7;
     6 vector<ll> v[qs];
     7 ll t,n,in[qs];
     8 bool u[qs];
     9 void topsort(){    //拓扑排序处理环 
    10     queue<ll> q;
    11     for(int i=1;i<=n;++i) if(in[i]==1) q.push(i);
    12     while(q.size()){
    13         ll t=q.front(); q.pop();
    14         u[t]=1;
    15         int Si=v[t].size();
    16         for(int i=0;i<Si;++i){
    17             int x=v[t][i];
    18             if(in[x]>1){
    19                 in[x]--;
    20                 if(in[x]==1) q.push(x);
    21             }
    22         }
    23     }
    24 }
    25 ll dfs(int x,int fa){   //dfs求环上节点分支上节点总数 
    26     ll Si=v[x].size(),res=0;
    27     for(int i=0;i<Si;++i){
    28         ll fx=v[x][i];
    29         if(u[fx]&&fx!=fa){
    30             res+=dfs(fx,x);
    31             res++;
    32         }
    33     }
    34     return res;
    35 }
    36 ll cal(ll x){        // 排列组合 去重 
    37     return x*(x-1)/2;
    38 }
    39 int main(){
    40     std::ios::sync_with_stdio(false);
    41     cin>>t;
    42     while(t--){
    43         cin>>n;
    44         for(int i=0;i<=n;++i){
    45             v[i].clear(); in[i]=u[i]=0;
    46         }
    47         int x,y;
    48         for(int i=1;i<=n;++i){
    49             cin>>x>>y;
    50             v[x].push_back(y); in[x]++;
    51             v[y].push_back(x); in[y]++;
    52         }
    53         topsort();
    54         ll ans=n*(n-1);        //最好情况下的总路径数 
    55         for(int i=1;i<=n;++i){
    56             if(!u[i]){
    57                 ll cnt=dfs(i,0);
    58                 ans-=cal(cnt+1);    //去重 
    59             }
    60         }
    61         cout<<ans<<"
    ";
    62     }
    63     return 0;
    64 }
  • 相关阅读:
    C语言文本文件实现局部修改
    TTMS框架设计思路及实例介绍
    浅谈函数与操作符的重载
    Java:继承与多态
    Java:类与对象(二)
    Java : 类与对象(一)
    C语言 数的阶乘、高次幂、大数加法及大数乘法
    C语言下的位运算
    enum:枚举类型介绍与简单使用
    C语言实现字符界面下的学生管理成绩系统
  • 原文地址:https://www.cnblogs.com/Suki-Sugar/p/14038964.html
Copyright © 2020-2023  润新知