2019CCPC秦皇島賽區(重現賽)- 感謝東秦&復旦 hdu6736 dfs+快速冪

Problem Description

Z 國近年來一直在考慮遏制國土沙漠化的方案。在 Z 國廣闊的疆域上,有着許多的沙漠。沙漠上乾旱少雨,荒無人煙,僅有仙人掌能在這種魔鬼環境中生存。經過 Z 國地質探測局的調查,他們得到了沙漠的實地情況。Z 國的地質探測局是一個熱愛 CCPC 的機構,他們喜歡使用圖論的方式來描述看到的景色。在得到的數據中,沙漠中的每一個連通塊都是一棵仙人掌;一個連通塊是一棵仙人掌當且僅當連通塊中不存在重邊和自環,並且每一條邊僅被至多一個簡單環覆蓋。

經過一番評估,Z 國決定通過刪去沙漠中的一些邊,最終將沙漠變爲森林。這裏我們定義森林滿足:森林中每一個連通塊都是一棵樹,而樹是邊數等於點數減一的連通塊。現在給定一個包含 n 個點的沙漠,請你求出 Z 國一共有多少種滿足要求的沙漠改造方案。兩種方案不同當且僅當方案中被刪去的邊集不同。由於答案可能很大,請將最終答案對 998244353 取模後輸出。

 

 

Input

多組數據,每組數據第一行輸入兩個非負整數 n、m,分別表示沙漠中的點數和邊數。沙漠中點的編號爲 1, 2, ..., n。

對於每組數據的第 2 到第 m+1 行,每行輸入兩個正整數 u、v,表示沙漠中編號爲 u 和編號爲 v 的兩個點之間有邊相連。

1≤T≤3,1≤n≤3×105,m≤5×105,1≤u, v≤n 並且 u≠v。
 

Hint


樣例解釋

對於第一組樣例,只需要至少刪去一條邊即可變爲森林,故一共有 23−1=7 種方案。

 

 

Output

對於每一組數據,輸出一行一個非負整數,表示答案對 998244353 取模後的值。

 

 

Sample Input


 

2 3 3 1 2 2 3 3 1 6 6 1 2 2 3 3 1 2 4 4 5 5 2

 

 

Sample Output


 

7 49

 

 

Source


 

642ccpcQHD

 

題解:關於有環是

無環的要計算在一起,計算

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mem(s) memset(s, 0, sizeof(s))
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
const int maxn = 1e6+5;
const int mod = 998244353;
int vis[maxn],f[maxn];
ll res=1,res2=0;
int n,m,flag;
vector<int>G[maxn];
void init(){
    memset(vis,0,sizeof(vis));
    res=1,flag=0;
    for(int i=1;i<=n;i++)G[i].clear();
}
ll mul(ll a,ll b){
    return (a%mod)*(b%mod)%mod;
}
ll q_pow(ll a,ll b){
    ll ans=1;
    while(b){
        if(b&1)ans=mul(ans,a);
        a=mul(a,a); 
        b>>=1;
    }
    return ans;
}
void dfs(int fa,int u,int d){
    //cout<<u<<endl;
    vis[u]=1;f[u]=d;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v==fa)continue;
        if(vis[v]){
            if(d>f[v]){
                flag=1;
                res2+=d-f[v]+1;
                res=mul(res,(q_pow(2,d-f[v]+1)-1+mod)%mod);
            }
        }else {
            dfs(u,v,d+1);
        }
    }
}

int main() 
{
    while(scanf("%d%d",&n,&m)!=EOF){
        init();
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        ll ans=1;
        for(int i=1;i<=n;i++){
            res=1;
            if(!vis[i]){
                dfs(-1,i,1);
                ans=mul(res,ans);
            }
        }
        printf("%lld\n",mul(ans,q_pow(2,m-res2)));
    }
    return 0;
}
/*
3 2
1 2
2 3
*/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章