import java.util.Scanner;
public class Main {
public static void main(String[] arg) {
Scanner scanner = new Scanner(System.in);
// todo
}
}
NC20525. [ZJOI2017]仙人掌
描述
输入描述
多组数据,第一行输入一个整数T表示数据组数。
每组数据第一行输入两个整数n,m,表示图中的点数与边数。
接下来m行,每行两个整数u,v(1 ≤ u,v ≤ n,u!=v)表示图中的一条边。
保证输入的图联通且没有自环与重边
Sigma(n) ≤ 5*10^5,m ≤ 10^6,1 ≤ m ≤ n*(n-1)/2
输出描述
对于每组数据,输出一个整数表示方案数,当然方案数可能很大,请对998244353取模后输出。
示例1
输入:
2 3 2 1 2 1 3 5 4 1 2 2 3 2 4 1 5
输出:
2 8
说明:
对于第一组样例合法加边的方案有 {}, {(2,3)},共 2 种。C++14(g++5.4) 解法, 执行用时: 773ms, 内存消耗: 86744K, 提交时间: 2019-03-14 18:06:23
#include<cstdio>#include<iostream>#include<algorithm>#include<cstdlib>#include<cstring>#include<string>#include<climits>#include<vector>#include<cmath>#include<map>#include<set>#define LL long longusing namespace std;inline char nc(){static char buf[100000],*p1=buf,*p2=buf;if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }return *p1++;}inline void read(int &x){char c=nc();int b=1;for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}inline void read(LL &x){char c=nc();LL b=1;for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}inline int read(char *s){char c=nc();int len=0;for(;!(c>='A' && c<='Z');c=nc()) if (c==EOF) return 0;for(;(c>='A' && c<='Z');s[len++]=c,c=nc());s[len++]='\0';return len;}inline void read(char &x){for (x=nc();!(x>='A' && x<='Z');x=nc());}int wt,ss[19];inline void print(int x){if (x<0) x=-x,putchar('-');if (!x) putchar(48); else {for (wt=0;x;ss[++wt]=x%10,x/=10);for (;wt;putchar(ss[wt]+48),wt--);}}inline void print(LL x){if (x<0) x=-x,putchar('-');if (!x) putchar(48); else {for (wt=0;x;ss[++wt]=x%10,x/=10);for (;wt;putchar(ss[wt]+48),wt--);}}int T,n,m,s,flag,v[500010];vector<int> b[500010];LL g[500010],f[500010];const LL mo=998244353;struct tree{int a,b,dfs,low;}a[500010];map<int,bool> c[500010];int dep[500010],dfn[500010],fa[500010],lu[500010],cnt;void init(){for (int i=1;i<=n;i++)b[i].clear(),a[i].dfs=a[i].low=a[i].a=a[i].b=0,c[i].clear(),dfn[i]=0,dep[i]=0,fa[i]=0;g[1]=1LL,g[0]=1LL;for (int i=2;i<=n;i++)g[i]=(g[i-1]+g[i-2]*(LL)(i-1)%mo)%mo;}void dfs(int x,int p){fa[x]=p,dfn[x]=++cnt,dep[x]=dep[p]+1;for (int i=0;i<b[x].size();i++)if (!dfn[b[x][i]]) dfs(b[x][i],x);}bool check(){cnt=0;dfs(1,0);int u,v;memset(lu,0,sizeof(lu));for (int i=1;i<=n;i++)for (int j=0;j<b[i].size();j++)if (i<b[i][j]){u=i,v=b[i][j];if (dfn[u]<dfn[v]) swap(u,v);while (u!=v){if (lu[u]==2) return false;lu[u]++,u=fa[u];}}return true;}void dp(int x,int y){v[x]=1;f[x]=1;int sum=0;for (int i=0;i<b[x].size();i++)if (!v[b[x][i]] && !c[x][b[x][i]]){dp(b[x][i],y);f[x]=f[x]*f[b[x][i]]%mo;sum++;}if (x==y) f[x]=f[x]*g[sum]%mo;else f[x]=f[x]*g[sum+1]%mo;}void work(int x){for (int i=0;i<b[x].size();i++)if (v[b[x][i]] && b[x][i]!=fa[x]){int y=b[x][i];c[x][y]=1,c[y][x]=1;while (x!=y){c[x][fa[x]]=1;c[fa[x]][x]=1;x=fa[x];}return ;}else if (!v[b[x][i]])v[b[x][i]]=1,fa[b[x][i]]=x,work(b[x][i]),v[b[x][i]]=0;}int main(){read(T);while(T--){read(n);read(m);int x,y;init();for (int i=1;i<=m;i++)read(x),read(y),b[x].push_back(y),b[y].push_back(x);if (!check()) {print(0),puts("");continue;}for(int i=1;i<=n;i++) v[i]=0;v[1]=1;work(1);LL res=1;for(int i=1;i<=n;i++) v[i]=0;for (int i=1;i<=n;i++)if (!v[i]) dp(i,i),res=res*f[i]%mo;print(res);puts("");}return 0;}
C++11(clang++ 3.9) 解法, 执行用时: 358ms, 内存消耗: 23672K, 提交时间: 2019-03-09 14:12:12
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>using namespace std;typedef long long ll;inline int read(){int x=0;char ch=getchar();while(ch<'0' || '9'<ch)ch=getchar();while('0'<=ch && ch<='9')x=x*10+(ch^48),ch=getchar();return x;}const int N=5e5+9;const int M=1e6+9;const int md=998244353;int to[M],nxt[M],beg[N],tot;int n,m,fa[N],dep[N],dfn[N],path[N],a[N],dfs_clock;ll f[N],g[N],ans;inline void adde(int u,int v){to[++tot]=v;nxt[tot]=beg[u];beg[u]=tot;}inline void add(int u,int v){adde(u,v),adde(v,u);}void dfs(int u){dfn[u]=++dfs_clock;for(int i=beg[u],v;i;i=nxt[i])if((v=to[i])!=fa[u] && !dfn[v]){fa[v]=u;dep[v]=dep[u]+1;dfs(v);}}inline bool cmp(int a,int b){return dep[a]<dep[b];}void dfs2(int u,bool isrt){f[u]=1;path[u]=-1;int soncnt=0;for(int i=beg[u],v;i;i=nxt[i])if((v=to[i])!=fa[u] && path[v]==1){soncnt++;dfs2(v,0);(f[u]*=f[v])%=md;}if(soncnt==0)return;if(isrt)(f[u]*=g[soncnt])%=md;else(f[u]*=g[soncnt+1])%=md;}int main(){g[0]=g[1]=1;for(int i=2;i<N;i++)g[i]=(g[i-1]+g[i-2]*(i-1))%md;int T=read();while(T--){n=read();m=read();tot=1;for(int i=1;i<=n;i++)beg[i]=fa[i]=dfn[i]=dep[i]=path[i]=0;for(int i=1;i<=m;i++)add(read(),read());tot=0;dep[1]=1;fa[1]=0;dfs(1);for(int i=1;i<=m;i++){int st=to[i<<1],ed=to[i<<1|1];if(dfn[st]<dfn[ed])swap(st,ed);while(st!=ed){path[st]++;if(path[st]>2)goto wa;st=fa[st];}}if(0){wa:;puts("0");continue;}for(int i=1;i<=n;i++)a[i]=i;sort(a+1,a+n+1,cmp);ans=1ll;for(int i=1;i<=n;i++)if(path[a[i]]!=-1){dfs2(a[i],1);(ans*=f[a[i]])%=md;}printf("%lld\n",ans);}return 0;}