[多校2015.02.1006 高斯消元] hdu 5305 Friends

来源:互联网 发布:高拍仪软件电脑摄像头 编辑:程序博客网 时间:2024/06/16 09:38

题意:

给你n个人m条关系

每条关系包含a,b

代表a和b可以是线上朋友也可以是线下朋友

然后保证每个人的线上朋友数和线下朋友数相等

问你有多少种组成方法

思路:

官方题解是爆搜+剪枝,然而并不会写。。

比赛的时候想到用高斯消元来剪枝

最后枚举自由元

因为关系的话到了最后肯定有些关系是确定的。

这样一定会消掉一些部分

最后G++AC C++TLE。。

代码:

#include"cstdlib"#include"cstdio"#include"cstring"#include"cmath"#include"queue"#include"algorithm"#include"iostream"using namespace std;int equ,var;int x[55],du[55];int a[55][55];int nofree_num;int gcd(int x,int y){    return y?gcd(y,x%y):x;}int lcm(int x,int y){    return x/gcd(x,y)*y;}void debug(){    for(int i=0; i<equ; i++)    {        for(int j=0; j<=var; j++) printf("%d ",a[i][j]);        puts("");    }    puts("");}int dfs(int p){    int ans=0;    if(p<nofree_num)    {        int i,j;        for(i=nofree_num-1; i>=0; i--)        {            int tep=a[i][var];            for(j=i+1; j<var; j++) tep=tep-(x[j]*a[i][j]);            if(tep%a[i][i]!=0) return 0;            x[i]=tep/a[i][i];        }        for(i=0; i<equ; i++) if(x[i]!=1 && x[i]!=-1) return 0;        return 1;    }    x[p]=-1;    ans+=dfs(p-1);    x[p]=1;    ans+=dfs(p-1);    return ans;}int gauss(){    int i,j,k;    int row,col;    for(row=0,col=0; row<equ&&col<var; row++,col++)    {        int maxr=row;        for(i=row+1; i<equ; i++) if(abs(a[i][col])>abs(a[maxr][col])) maxr=i;        if(a[maxr][col]==0)        {            row--;            continue;        }        for(i=0; i<=var; i++) swap(a[row][i],a[maxr][i]);        for(i=row+1; i<equ; i++)        {            if(a[i][col])            {                int LCM=lcm(abs(a[row][col]),abs(a[i][col]));                int ta=LCM/abs(a[row][col]);                int tb=LCM/abs(a[i][col]);                if(a[i][col]*a[row][col]<0) ta=-ta;                for(j=col; j<=var; j++)                    a[i][j]=(a[i][j]*tb)-(a[row][j]*ta);            }        }    }    for(i=row; i<equ; i++) if(a[i][var]) return 0;    for(i=0; i<equ; i++)    {        if(a[i][i]==0)        {            for(j=i+1; j<var; j++) if(a[i][j]) break;            if(j==var) break;            for(k=0; k<equ; k++) swap(a[k][i],a[k][j]);        }    }    nofree_num=row;    //debug();    if(var-nofree_num)    {        return dfs(var-1);    }    for(i=row-1; i>=0; i--)    {        int tep=a[i][var];        for(j=i+1; j<var; j++) tep=tep-(x[j]*a[i][j]);        if(tep%a[i][i]!=0) return 0;        x[i]=(tep/a[i][i]);        if(x[i]!=1 && x[i]!=-1) return 0;    }    return 1;}int main(){    int t;    cin>>t;    while(t--)    {        int n,m;        scanf("%d%d",&n,&m);        equ=m;        var=m;        memset(a,0,sizeof(a));        memset(du,0,sizeof(du));        for(int i=0; i<m; i++)        {            int x,y;            scanf("%d%d",&x,&y);            du[x]++;            du[y]++;            a[x-1][i]=1;            a[y-1][i]=1;        }        int ff=1;        for(int i=1;i<=n;i++)        {            if(du[i]%2)            {                ff=0;                break;            }        }        if(ff==0)        {            puts("0");            continue;        }       // debug();        int ans=gauss();        printf("%d\n",ans);    }    return 0;}


0 0