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

题意:

给你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;
}
时间: 2024-08-10 21:27:45

[多校2015.02.1006 高斯消元] hdu 5305 Friends的相关文章

2014多校第一场J题 || HDU 4870 Rating(DP || 高斯消元)

题目链接 题意 :小女孩注册了两个比赛的帐号,初始分值都为0,每做一次比赛如果排名在前两百名,rating涨50,否则降100,告诉你她每次比赛在前两百名的概率p,如果她每次做题都用两个账号中分数低的那个去做,问她最终有一个账号达到1000分需要做的比赛的次数的期望值. 思路 :可以直接用公式推出来用DP做,也可以列出210个方程组用高斯消元去做. (1)DP1:离散化.因为50,100,1000都是50的倍数,所以就看作1,2,20.这样做起来比较方便. 定义dp[i]为从 i 分数到达i+1

【弱校胡策】2016.4.14 (bzoj2164)最短路+状压DP+矩阵乘法+高斯消元+树链剖分+线段树+背包DP

cyyz&qhyz&lwyz&gryz弱校胡策 命题人:cyyz ws_fqk T3暴力写挫了 50+10+0滚粗辣! 奇妙的约会(appointment.cpp/c/pas) [问题描述] DQS和sxb在网上结识后成为了非常好的朋友,并且都有着惊人 的OI水平.在NOI2333的比赛中,两人均拿到了金牌,并保送进入 HU/PKU.于是两人决定在这喜大普奔的时刻进行面基. NOI2333参赛选手众多,所以安排了n个考点,DQS在1号考点, 而sxb在n号考点.由于是举办全国性赛事

2015南阳CCPC E - Ba Gua Zhen 高斯消元 xor最大

Ba Gua Zhen Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 无 Description During the Three-Kingdom period, there was a general named Xun Lu who belonged to Kingdom Wu. Once his troop were chasing Bei Liu, he was stuck in the Ba Gua Zhen from Liang Zhuge.

poj_1222_高斯消元

第一次学习使用高斯消元,将灯板化为线性方程组,进行求解. /*######################################################################### # File Name: poj_1222.cpp # Author: CaoLei # Created Time: 2015/7/20 15:48:04 ###################################################################

hdu-5833 Zhu and 772002(高斯消元)

题目链接: Zhu and 772002 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1006    Accepted Submission(s): 348 Problem Description Zhu and 772002 are both good at math. One day, Zhu wants to test the

HDU 4870 Rating(高斯消元 )

HDU 4870   Rating 这是前几天多校的题目,高了好久突然听旁边的大神推出来说是可以用高斯消元,一直喊着赶快敲模板,对于从来没有接触过高斯消元的我来说根本就是一头雾水,无赖之下这几天做DP,正好又做到了这个题,没办法得从头开始看,后来在网上找了别人的高斯消元的模板后发现其实也还是很好理解,就是先构造一个增广矩阵,然后化行阶梯形,最后迭代求解 首先有一个介绍高斯消元感觉过于详细的博客http://blog.csdn.net/tsaid/article/details/7329301 首

HDU 4870 Rating(高斯消元)

HDU 4870 Rating 题目链接 题意:一个人注册两个账号,初始rating都是0,他每次拿低分的那个号去打比赛,赢了加50分,输了扣100分,胜率为p,他会打到直到一个号有1000分为止,问比赛场次的期望 思路:f(i, j)表示i >= j,第一个号i分,第二个号j分时候,达到目标的期望,那么可以列出转移为f(i, j) = p f(i', j') + (1 - p) f(i'' + j'') + 1 f(i', j')对应的是赢了加分的状态,f(i'', j'')对应输的扣分的状态

【BZOJ 4171】 4171: Rhl的游戏 (高斯消元)

4171: Rhl的游戏 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 74  Solved: 33[Submit][Status][Discuss] Description RHL最近迷上一个小游戏:Flip it.游戏的规则很简单,在一个N*M的格子上,有一些格子是黑色,有一些是白色 .每选择一个格子按一次,格子以及周围边相邻的格子都会翻转颜色(边相邻指至少与该格子有一条公共边的格子 ),黑变白,白变黑.RHL希望把所有格子都变成白色的.不幸

POJ 1830 开关问题 高斯消元,自由变量个数

http://poj.org/problem?id=1830 如果开关s1操作一次,则会有s1(记住自己也会变).和s1连接的开关都会做一次操作. 那么设矩阵a[i][j]表示按下了开关j,开关i会被操作一次,记得a[i][i] = 1是必须的,因为开关i操作一次,本身肯定会变化一次. 所以有n个开关,就有n条方程, 每个开关的操作次数总和是:a[i][1] + a[i][2] + ... + a[i][n] 那么sum % 2就代表它的状态,需要和(en[i] - be[i] + 2) % 2