1. 程式人生 > >線代之高斯消元

線代之高斯消元

led 復雜度 med i++ byte mes center .com sent

數學上,高斯消元法(或譯:高斯消去法),是線性代數規劃中的一個算法,可用來為線性方程組求解。但其算法十分復雜,不常用於加減消元法,求出矩陣的秩,以及求出可逆方陣的逆矩陣。不過,如果有過百萬條等式時,這個算法會十分省時。一些極大的方程組通常會用叠代法以及花式消元來解決。當用於一個矩陣時,高斯消元法會產生出一個“行梯陣式”。高斯消元法可以用在電腦中來解決數千條等式及未知數。亦有一些方法特地用來解決一些有特別排列的系數的方程組。

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

線代之高斯消元