线代之高斯消元

数学上,高斯消元法(或译:高斯消去法),是线性代数规划中的一个算法,可用来为线性方程组求解。但其算法十分复杂,不常用于加减消元法,求出矩阵的秩,以及求出可逆方阵的逆矩阵。不过,如果有过百万条等式时,这个算法会十分省时。一些极大的方程组通常会用迭代法以及花式消元来解决。当用于一个矩阵时,高斯消元法会产生出一个“行梯阵式”。高斯消元法可以用在电脑中来解决数千条等式及未知数。亦有一些方法特地用来解决一些有特别排列的系数的方程组。

2968: Lights 

Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByte
Total Submit: 8            Accepted:1

Description

Bessie and the cows were playing games in the barn, but the power was reset and the lights were all turned off. Help the cows get all the lights back on so they can resume their games.

The N (1 ≤ N ≤ 35) lights conveniently numbered 1..N and their switches are arranged in a complex network with M (1 ≤ M ≤ 595) clever connection between pairs of lights (see below).

Each light has a switch that, when toggled, causes that light -- and all of the lights that are connected to it -- to change their states (from on to off, or off to on).

Find the minimum number of switches that need to be toggled in order to turn all the lights back on.

It‘s guaranteed that there is at least one way to toggle the switches so all lights are back on.

Input

* Line 1: Two space-separated integers: N and M.

* Lines 2..M+1: Each line contains two space-separated integers representing two lights that are connected. No pair will be repeated.

Output

* Line 1: A single integer representing the minimum number of switches that need to be flipped in order to turn on all the lights.

Sample Input

5 6
1 2
1 3
4 2
3 4
2 5
5 3

Sample Output

3

这个题我有两个思路一个是保存状态二分,但是显然时间很长

所以这种问题要使用高斯消元,高斯消元在解决矩阵的问题可是神神器,因为暴力得到某种状态的复杂度会很高

卿学姐的算法讲堂也有介绍这个,感兴趣的可以去看下学习下

他的引入是解方程,其实就是解矩阵,这个以前叫代入消元吧

#include<stdio.h>
#include<algorithm>
using namespace std;
int n,m,ans=0x3f3f3f3f,a[37][37],x[37];
void gauss()
{
    for(int k=1; k<=n; k++)
    {
        int bj=k;
        for(int i=k+1; i<=n; i++)if(a[i][k])
            {
                bj=i;
                break;
            }
        if(bj!=k)
            for(int j=1; j<=n+1; j++)
                swap(a[bj][j],a[k][j]);
        for(int i=k+1; i<=n; i++)
            if(a[i][k])
            {
                for(int j=1; j<=n+1; j++)
                    a[i][j]^=a[k][j];
            }
    }
}
void dfs(int xx,int tot)
{
    if(tot>ans)return;
    if(!xx)
    {
        ans=min(ans,tot);
        return;
    }
    if(a[xx][xx])
    {
        x[xx]=a[xx][n+1];
        for(int j=n; j>xx; j--)x[xx]^=x[j]&a[xx][j];
        if(x[xx])dfs(xx-1,tot+1);
        else dfs(xx-1,tot);
    }
    else
    {
        x[xx]=0;
        dfs(xx-1,tot);
        x[xx]=1;
        dfs(xx-1,tot+1);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        a[x][y]=a[y][x]=1;
    }
    for(int i=1; i<=n; i++)
        a[i][n+1]=1,a[i][i]=1;
    gauss();
    dfs(n,0);
    printf("%d",ans);
    return 0;
}
时间: 2024-10-09 06:31:51

线代之高斯消元的相关文章

(高斯消元)HDU 5006 Resistance 2014 鞍山网赛

题目链接 题意:有一个电路,用0/1的电阻连接起来.给定两点,问之间的电阻为多少? 先回忆一下中学物理知识,若用并联串联去做,碰到复杂电路根本分析不清.这里用到基尔霍夫定理. 在任一瞬时,流向某一结点的电流之和恒等于由该结点流出的电流之和. 在任一瞬间,沿电路中的任一回路绕行一周,在该回路上电动势之和恒等于各电阻上的电压降之和. 那么我们对于图中的点(电阻为0的看作一个点,缩点)都可以列方程  ∑(Ua-Ub)/Rab =0 Rab都是1所以某条边的电流就等于电压差了. 为了方便求结果,我们设S

【枚举】【高斯消元】Gym - 101412D - Find the Outlier

给你一个未知的d次多项式在0,1,...,d+2处的取值,其中有且只有一个是错的,问你哪个是错的. 枚举哪个是错的,再在剩下的d+2个中取d+1个高斯消元,解出多项式系数,然后代一下最后剩下的那个数看看是否合法,如果合法再看看那个错的是否真的错了. #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> using namespace std; #define N 11 d

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

题意: 给你n个人m条关系 每条关系包括a,b 代表a和b能够是线上朋友也能够是线下朋友 然后保证每一个人的线上朋友数和线下朋友数相等 问你有多少种组成方法 思路: 官方题解是爆搜+剪枝,然而并不会写. . 比赛的时候想到用高斯消元来剪枝 最后枚举自由元 由于关系的话到了最后肯定有些关系是确定的. 这样一定会消掉一些部分 最后G++AC C++TLE. . 代码: #include"cstdlib" #include"cstdio" #include"cs

高斯消元【转】

转载注明出处 高消一直是ACM中高层次经常用到的算法,虽然线性代数已经学过,但高消求解的问题模型及高消模板的应用变化是高消的最复杂之处. 先介绍一下高消的基本原理:引入互联网czyuan的帖子: 高斯消元法,是线性代数中的一个算法,可用来求解线性方程组,并可以求出矩阵的秩,以及求出可逆方阵的逆矩阵. 高斯消元法的原理是: 若用初等行变换将增广矩阵 化为 ,则AX = B与CX = D是同解方程组. 所以我们可以用初等行变换把增广矩阵转换为行阶梯阵,然后回代求出方程的解. 以上是线性代数课的回顾,

[bzoj3601] 一个人的数论 [莫比乌斯反演+高斯消元]

题面 传送门 思路 这题妙啊 先把式子摆出来 $f_n(d)=\sum_{i=1}^n[gcd(i,n)==1]i^d$ 这个$gcd$看着碍眼,我们把它反演掉 $f_n(d)=\sum_{i=1}^n\sum_{j|i,j|n}\mu(j)i^d=\sum_{j|n}\mu(j)\sum_{i=1}^{\frac{n}{j}}(ij)^d=\sum_{j|n}\mu(j)j^d\sum_{i=1}^{\frac{n}{j}}i^d$ 那么最后面这个东西就是个自然数幂求和了 在这篇关于斯特林数的

poj_1222_高斯消元

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

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