bzoj2582[Usaco2012Jan]Bovine Alliance

来源:互联网 发布:国家发改委 大数据 编辑:程序博客网 时间:2024/06/03 14:52

题意明显。
一开始不带脑子看题,写了个最大匹配方案数直接交上去了。。也没测样例,WA了一发。。
然后才认真看了看题目,发现是道思考题目。。
然后就萎了,没想出来,可能是没认真想,感觉结论挺显然的。。
就是,假设我们分出来的一部分的边数位E,点数为V。
为了保证每个边都属于一个点,E<=V。
所以根据题意现在只有可能两种情况。。

一.E=V
在这种情况下,肯定知道当前这一组有个环,那么我们把环去掉可以发现剩下的方案数是唯一的,而环的方案只有两种(反向),所以ans*=2.

二.E=V-1
这种情况下,有一个点是空出来的,我们可以发现,这个空出来的点可以由1-V轮流替换,所以这种情况下的方案就是ans*=v;

E更小的话就不符合最优策略了。

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)#define inf 0xc3c3c3c3using namespace std;const int N=5e5+5;const int mo=1e9+7;typedef long long ll;int result[N],vis[N],tot=1;int head[N],next[N],go[N],bz[N];int n,m;int E,V;inline void add(int x,int y){    go[++tot]=y;    next[tot]=head[x];    head[x]=tot;}inline void dfs(int x){    vis[x]=1;    ++V;    for(int i=head[x];i;i=next[i])    {        int v=go[i];        if (!bz[i])        {            bz[i]=bz[i^1]=1,++E;            if (!vis[v])dfs(v);        }     }}int main(){    scanf("%d%d",&n,&m);    fo(i,1,m)    {        int x,y;        scanf("%d%d",&x,&y);        add(x,y);        add(y,x);    }    int ans=1;    fo(i,1,n)    if (!vis[i])    {        E=V=0;        dfs(i);        if (E>V)        {            printf("0\n");            return 0;        }        if (V==E)ans=ans*2%mo;        else ans=1ll*ans*V%mo;        //printf("%d\n",ans);    }    printf("%d\n",ans);}