three
7月9日
testC
总时间限制:
10000ms
内存限制:
128000kB
描述
N个点M条边的无向图,当然可以连通也可以不连通。
现在你需要知道多少条边才可能使图连通,假设这个答案是T。
现在你需要求出用T条边把这个图连通需要多少种方案?
两种方案X和Y不同的定义为:其中至少有一条在X中的边不存在于Y中。
输出这个答案模K的结果。
输入
第一行三个数N,M,K分别表示点数,边数,模数。
输出
一行一个数,表示最后答案模K的结果。
样例输入
4 1 1000000000
1 4
样例输出
8
提示
数据范围:N,M<=10^5
#include<cstdio>
#include<cstring>
#include<iostream>
#define PROC "testC"
using namespace std;
const int MAXN = 100005;
int fa[MAXN],ne;
struct Edge
{
int to;
Edge * next;
} e[MAXN *2],*head[MAXN];
bool b[MAXN];
int ngroup = 0;
int g[MAXN];
int k ;
long long pow(int p,int q)
{
long long ans = 1,t = p;
while (q)
{
if (q & 1)
ans *=t % k;
t*=t %k;
q>>=1;
}
return ans % k;
}
void addedge(int f,int to)
{
e[++ne].to = to;
e[ne].next = head[f];
head[f] = e+ne;
return;
}
void findg(int now)
{
for (Edge * p = head[now];p;p=p->next)
{
if (!b[p->to])
{
b[p->to] = true;
g[ngroup]++;
findg(p->to);
}
}
return;
}
int main()
{
// freopen("test3.in.cpp","r",stdin);
// freopen("testC.out","w",stdout);
int n,m;
scanf("%d%d%d",&n,&m,&k);
int f,to;
for (int i = 0;i<m;i++)
{
scanf("%d%d",&f,&to);
addedge(f,to);
addedge(to,f);
}
for (int i = 1;i<=n;i++)
{
if (!b[i])
{ b[i] = true;
g[++ngroup] = 1;
findg(i);
}
}
long long ans = 1;
/*for (int i = 1;i<ngroup;i++)
for (int j =i+1;j<=ngroup;j++)
ans =(ans + sum%(g[i]*g[j]*k)/(g[i]*g[j]))%k;*/
for (int i = 1;i<=ngroup;i++)
ans =ans * g[i] % k;
if (ngroup==1) ans =1;
else
for (int i = 1;i<=ngroup-2;i++)
ans =ans * n %k;
// cout<<ngroup<<endl;
// ans = ( (ans % k) * (pow(n,ngroup-2))) % k;
cout<<ans%k;
return 0;
}
错因:
- 1. 未完待续
- 2. 未完待续
- 3. 正解:连通块个数讨论,找出规律,正确的推导过程不是很明了。大概到n=4,就可以看出来。
做:计算方案数时出现了遗漏
改:无
得:要正确认识自己设定的变量含义找规律要认真