博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ1770:[USACO]lights 燈(高斯消元,DFS)
阅读量:6168 次
发布时间:2019-06-21

本文共 2401 字,大约阅读时间需要 8 分钟。

Description

貝希和她的閨密們在她們的牛棚中玩遊戲。但是天不從人願,突然,牛棚的電源跳閘了,所有的燈都被關閉了。貝希是一個很膽小的女生,在伸手不見拇指的無盡的黑暗中,她感到驚恐,痛苦與絕望。她希望您能夠幫幫她,把所有的燈都給重新開起來!她才能繼續快樂地跟她的閨密們繼續玩遊戲! 牛棚中一共有N(1 <= N <= 35)盞燈,編號為1到N。這些燈被置於一個非常複雜的網絡之中。有M(1 <= M <= 595)條很神奇的無向邊,每條邊連接兩盞燈。 每盞燈上面都帶有一個開關。當按下某一盞燈的開關的時候,這盞燈本身,還有所有有邊連向這盞燈的燈的狀態都會被改變。狀態改變指的是:當一盞燈是開著的時候,這盞燈被關掉;當一盞燈是關著的時候,這盞燈被打開。 問最少要按下多少個開關,才能把所有的燈都給重新打開。 數據保證至少有一種按開關的方案,使得所有的燈都被重新打開。

Input

*第一行:兩個空格隔開的整數:N和M。

*第二到第M+1行:每一行有兩個由空格隔開的整數,表示兩盞燈被一條無向邊連接在一起。 沒有一條邊會出現兩次。

Output

第一行:一個單獨的整數,表示要把所有的燈都打開時,最少需要按下的開關的數目。

Sample Input

5 6
1 2
1 3
4 2
3 4
2 5
5 3
輸入細節:
一共有五盞燈。燈1、燈4和燈5都連接著燈2和燈3。

Sample Output

3
輸出細節:
按下在燈1、燈4和燈5上面的開關。

Solution

不能再这么颓了不然真的就要凉透了
还有这题目为什么是繁体的
搞死小圆高斯消元好强啊QAQ这个题的做法也好神奇啊
很容易可以发现,开关的顺序不会影响最终结果
那么到底应该怎么搞呢?举个栗子
有3盏灯,其中1和2连接,1和3不连接,那么我们可以列出一个方程
(1*ans[1])^(1*ans[2])^(0*ans[3])=1
ans[]表示这个灯有没有按。灯1本身或者和灯1相连的灯系数为1,否则为0
为什么这么列呢?很容易发现,如果为1的项的异或和为1,那么最后结果肯定是1
感性理解一下,应该挺好懂的
以此类推我们可以列出n个这样的方程,然后我们就可以用高斯消元来把这个矩阵消了
消异或矩阵和消普通矩阵是一样的,只不过是把加减的操作换成异或
 
消了之后不要记着求答案,因为答案里面可能有自由变元。
怎么办呢?可以用爆搜替代普通高斯消元的答案回带,
若当前行的答案固定就算出来,否则的话就枚举0/1记入答案。继续搜下一层。

Code

1 #include
2 #include
3 #include
4 #define N (50) 5 using namespace std; 6 7 int n,m,minn=0x7fffffff,u,v; 8 int f[N][N],ans[N],head[N],num_edge; 9 10 void Gauss()11 {12 for (int i=1; i<=n; ++i)13 {14 int num=i;15 for (int j=i+1; j<=n; ++j)16 if (f[j][i]>f[i][i])17 num=j;18 if (num!=i)19 for (int j=1; j<=n+1; ++j)20 swap(f[i][j],f[num][j]);21 for (int j=i+1; j<=n; ++j)22 if (f[j][i])23 for (int k=i; k<=n+1; ++k)24 f[j][k]^=f[i][k];25 }26 }27 28 void Dfs(int x,int now)29 {30 if (now>=minn) return;31 if (x==0) {minn=now; return;}32 33 if (f[x][x])34 {35 int t=f[x][n+1];36 for (int i=x+1; i<=n; ++i) t^=f[x][i]*ans[i];37 ans[x]=t;38 Dfs(x-1,now+(t==1));39 }40 else41 {42 ans[x]=0; Dfs(x-1,now);43 ans[x]=1; Dfs(x-1,now+1);44 }45 }46 47 int main()48 {49 scanf("%d%d",&n,&m);50 for (int i=1; i<=m; ++i)51 {52 scanf("%d%d",&u,&v);53 f[u][v]=f[v][u]=1;54 }55 for (int i=1; i<=n; ++i) f[i][n+1]=f[i][i]=1;56 Gauss();57 Dfs(n,0);58 printf("%d",minn);59 }

转载于:https://www.cnblogs.com/refun/p/8947070.html

你可能感兴趣的文章
NET反射系统
查看>>
Oracle12C本地用户的创建和登录
查看>>
使用JS制作一个鼠标可拖的DIV(一)——鼠标拖动
查看>>
《Javascript高级程序设计》阅读记录(三):第五章 上
查看>>
root方式细节剖析
查看>>
ios开发之--MJRefresh的简单使用
查看>>
Ionic3与Angular4新特性
查看>>
论文查重福利
查看>>
关注云端搜索技术:elasticsearch,nutch,hadoop,nosql,mongodb,hbase,cassandra 及Hadoop优化...
查看>>
poj2629
查看>>
python之面向对象之反射运用
查看>>
stark组件之分页【模仿Django的admin】
查看>>
块UI样式编辑器下实现NX的功能
查看>>
KMP HDOJ 4300 Clairewd's message
查看>>
NetCore偶尔有用篇:NetCore项目WebApi返回Json属性大小写
查看>>
11.Bean2Document-BEAN转document
查看>>
SVN:Previous operation has not finished; run 'cleanup' if it was interrupted
查看>>
ASP.NET Page执行顺序如:OnPreInit()、OnInit()
查看>>
新闻焦点切换flash应用
查看>>
在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口...
查看>>