E. Number of Simple Paths——(基环树)

总结

这个题用树形DP写的处理,比较麻烦,细节比较多,比赛WA了好几次,知道有基环树这个东西,所以就试着了解一下。

思路

基环树套路
1:先找环
2:在环上处理问题
两点之间的简单路径

  • 如果在环上,cnt=2
  • 如果不在环上,cnt=1

因此,反着思考,只需要考虑两点之间不在环上的点。
那么子问题就成了计算每个环上的点子树的个数。

题目链接

//#pragma comment(linker,"/STACK:1024000000,1024000000")
//#pragma GCC optimize(2)
//#pragma GCC target ("sse4")
#include<bits/stdc++.h>
//typedef long long ll;
#define ull         unsigned long long
//#define int       __int128
#define int         long long
#define F           first
#define S           second
#define endl        "\n"//<
#define eps         1e-6
#define base        131
#define lowbit(x)   (x&(-x))
#define db          double
#define PI          acos(-1.0)
#define inf         0x3f3f3f3f
#define MAXN        0x7fffffff
#define INF         0x3f3f3f3f3f3f3f3f
#define _for(i, x, y) for (int i = x; i <= y; i++)
#define for_(i, x, y) for (int i = x; i >= y; i--)
#define ferma(a,b)  pow(a,b-2)
#define mod(x)      (x%mod+mod)%mod
#define pb          push_back
#define decimal(x)  cout << fixed << setprecision(x);
#define all(x)      x.begin(),x.end()
#define rall(x)      x.rbegin(),x.rend()
#define memset(a,b) memset(a,b,sizeof(a));
#define IOS         ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
#ifndef ONLINE_JUDGE
#include "local.h"
#endif
template<typename T> inline T fetch()
{
     
    T ret;
    cin >> ret;
    return ret;
}
template<typename T> inline vector<T> fetch_vec(int sz)
{
     
    vector<T> ret(sz);
    for(auto& it: ret)
        cin >> it;
    return ret;
}
template<typename T> inline void makeUnique(vector<T>& v)
{
     
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
}
template<typename T> inline T max_(T a,T b)
{
     
    if(a>b)
        return a;
    return b;
}
template<typename T> inline T min_(T a,T b)
{
     
    if(a<b)
        return a;
    return b;
}
void file()
{
     
#ifdef ONLINE_JUDGE
#else
    freopen("D:/LSNU/codeforces/duipai/data.txt","r",stdin);
    freopen("D:/LSNU/codeforces/duipai/WA.txt","w",stdout);
#endif
}
void Match()
{
     
#ifdef ONLINE_JUDGE
#else
    Debug::Compare();
#endif // ONLINE_JUDGE
}
signed main()
{
     
    IOS;
    file();
    int t;
    cin>>t;
    while(t--)
    {
     
        int n;
        cin>>n;
        vector<int>vis(n+1),circle(n+1),G[n+1];
        stack<int>sta;
        bool tag=false;
        for(int i=0; i<n; i++)
        {
     
            int u,v;
            cin>>u>>v;
            G[u].pb(v);
            G[v].pb(u);
        }
        function<void(int,int)>dfs=[&](int u,int fat)
        {
     
            vis[u]=true;
            sta.push(u);
            for(auto v:G[u])
            {
     
                if(v==fat)
                    continue;
                if(vis[v])
                {
     
                    while(true)
                    {
     
                        int pos=sta.top();
                        sta.pop();
                        circle[pos]=true;
                        if(pos==v)
                            break;
                    }
                    tag=true;
                    return ;
                }
                dfs(v,u);
                if(tag)
                    return ;
            }
            sta.pop();
        };
        function<int(int,int)>dfs2=[&](int u,int fat)
        {
     
            int sum=1;
            for(auto v:G[u])
            {
     
                if(v==fat||circle[v])
                    continue;
                sum+=dfs2(v,u);
            }
            return sum;
        };
        dfs(1,0);
        int ans=n*(n-1);
        for(int i=1; i<=n; i++)
        {
     
            if(circle[i])
            {
     
                int num=dfs2(i,0);
                ans-=num*(num-1)/2;
            }
        }
        cout<<ans<<endl;

    }

    Match();
    return 0;
}

你可能感兴趣的:(#,树形DP)