three

79

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. 1.       未完待续
  2. 2.       未完待续
  3. 3.       正解:连通块个数讨论,找出规律,正确的推导过程不是很明了。大概到n=4,就可以看出来。

做:计算方案数时出现了遗漏

改:无

得:要正确认识自己设定的变量含义找规律要认真

原文地址:https://www.cnblogs.com/rubylan/p/3837528.html