.

来源:互联网 发布:红蜘蛛软件 路由器 编辑:程序博客网 时间:2024/06/11 04:35

题意: 有n个人在圆桌上吃饭,主人位置固定,给m个关系ki表示第i个人的旁边是第ki个人,问有多少种方式可以排列…
注:这是一个圆桌,所以要分左右两边的…
给你n个人和m个关系
并查集处理下每个联通块,对(全部联通块-1)(因为1号位固定)进行全排列
再对每个元素大于1的联通块进行ans*=2,因为他们可以调转顺序
最后还有个最蛋疼的就是
n==2输出1

//URAL 1962#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <map>using namespace std;typedef long long LL;#define MM(a,x)  memset(a,x,sizeof(a));//#define mp make_pair#define pb push_back#define x first#define y secondint mod=1e9+7;int f[200],w[200],sum[200],n,m;void init(){    for(int i=1;i<=n;i++)        w[i]=1,f[i]=i;}int findf(int x){    if(x==f[x])        return x;    else return findf(f[x]);}void mix(int a,int b){    a=findf(a);    b=findf(b);    w[a]=w[b]=w[a]+w[b];    f[a]=b;}bool mp[200][200];int main(){#ifdef LOCAL    freopen("in.txt","r",stdin);    //debug=1;#endif // LOCAL    cin>>n>>m;    init();    bool flag=0;    for(int i=1;i<=m;i++)    {        int v;        scanf("%d",&v);        if(mp[v][i]||mp[i][v]) continue;        sum[v]++;        sum[i]++;        if(sum[v]>2||sum[i]>2) flag=1;        mp[i][v]=mp[v][i]=1;        if(findf(i)!=findf(v))            mix(i,v);        else        {            if(w[findf(i)]!=n) flag=1;        }    }    if(n==2) cout<<1<<endl;   else  if(!n) cout<<0<<endl;    else {    if(!flag)    {        int cnt=0,ct=0;        for(int i=1;i<=n;i++)        {            if(f[i]==i)            {                if(w[i]>1) cnt++;                else ct++;            }        }        LL ans=1;        for(int i=1;i<=cnt+ct-1;i++)            ans=(ans*i)%mod;        if(w[findf(1)]==1)        {            ;        }        else        {            ans=(ans*2)%mod;            cnt--;        }        for(int i=1;i<=cnt;i++)        {            ans=(ans*2)%mod;        }        cout<<ans<<endl;    }    else cout<<0<<endl;    }    return 0;}
0 0
原创粉丝点击