码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-07-24 18:37:56      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:

题意:

给你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;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

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

标签:

原文地址:http://blog.csdn.net/wdcjdtc/article/details/47041119

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!