最大匹配=最小覆盖点证明。。。。orz,研究了一个晚上。

本文探讨了最大匹配等于最小覆盖点的原理,并通过具体的图例进行了解释。作者通过研究增广路径的特性,找到了匹配上的点并证明了它们能够覆盖所有边,从而推导出最小覆盖点的概念。

     今天晚上本来很瞌睡的,由于明天要讲题(天哪,抽到了我),其中有一道题目是用到了“最大匹配=最小覆盖点”的思想。怕明天哪个会问道为什么,所以我研究了一个晚上,在无语的帮助下稍微懂了。

    废话不多说了,下面是我的证明:

   这个Matrix67证明的很清楚了:http://www.matrix67.com/blog/archives/116  我只是发表一些自己的看法,同时巩固一下。

 首先我们求的最大匹配中显然每个边是会对对应两个点,我们要想找到其中的那么几个点覆盖到全部的边(即最小覆盖点)。那么,我们现在的任务就是找到这些在匹配上的点,且证明它可以覆盖所有的边。

 如图:

       我们根据增广路线的性质,从右边的没有匹配的点出发,根据“没有匹配,匹配,没有匹配……”这样的边走下去,直到没有边可走,每个拐角我们都用“”标记,那么左边已经标记的,和右边没有标记的点,肯定和匹配的边是一一对应的,因为:如果右边没有标记的点应该标记,那么由它出发的边应该是没有匹配的,而事实不是这样。,同样,要是左边标记了点应该没有标记的话,那么由他出发的边应该是没有匹配的,这样也是不存在的。。,就是说,一个匹配的边不可能左边标记了,右边没有标记了。   

   现在已经找到匹配上的点,现在证明这些点是可以覆盖所有的边的。因为:不可能存在一条边是左边没有标记的,右边标记了的。原因是,如果一条边没有被匹配,那么他的左端点就会被由这条边到达而标记。如果这条变被匹配了,那么他的右端点的标记就会是从左边过来的,左端点会被标记。  

  所以这些点是可以覆盖所有的边的,且这些点与所有匹配边是意义对应的。。。

  覆盖点就是>=最大匹配,所以要求每个匹配边取一个点,那么就是最小覆盖点的数目了。。


```cpp #include<bits/stdc++.h> using namespace std; const int N=1e5+5; int n; char s[N]; struct node{ int x,y,z; bool flag; }; node a[N]; int t; bool vis[N]; int dfs(int z){ a[++t].x=z; a[t].z=0x3f3f3f3f; int x=t; int ii=z+1; int i; for(i=z+1; i<=n; i++){ ii=i; if(s[i]=='('){ i=dfs(i)+1; ii=i; } else if(s[i]==')'){ a[x].y=i; return i; } else if(s[i]=='+'){ a[x].z=min(a[x].z,1); } else if(s[i]=='-'){ a[x].z=min(a[x].z,2); } else if(s[i]=='*'){ a[x].z=min(a[x].z,3); } else if(s[i]=='/'){ a[x].z=min(a[x].z,4); } } a[x].y=n; return i; } int main(){ cin >>s+1; n=strlen(s+1); int ttt=dfs(0); for(int i=2; i<=t; i++){ int x=a[i].x-1; int y=a[i].y+1; int orz1=0,orz2=0; if(s[x]=='+'){ orz1=max(orz1,1); } if(s[x]=='-'){ orz1=max(orz1,2); } if(s[x]=='*'){ orz1=max(orz1,3); } if(s[x]=='/'){ orz1=max(orz1,4); } if(s[y]=='+'){ orz2=max(orz2,1); } if(s[y]=='-'){ orz2=max(orz2,2); } if(s[y]=='*'){ orz2=max(orz2,3); } if(s[y]=='/'){ orz2=max(orz2,4); } if(orz2<=a[i].z){ if((orz1==1||orz1==3||orz1==0)&&orz1<=a[i].z){ a[i].flag=true; } if((orz1==2||orz1==4)&&orz1<a[i].z){ a[i].flag=true; } } } for(int i=2; i<=t; i++){ if(a[i].flag==true){ vis[a[i].x]=true; vis[a[i].y]=true; } } for(int i=1; i<=n; i++){ if(vis[i]==false){ cout <<s[i]; } } return 0; }``````cpp#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; struct ill{ int l,r,mi; bool no; }h[50001]; char a[100001]; int l,g; int work(int s) { int i; h[++g].l=s; h[g].mi=5; int x=g; for(i=s+1;i<=l;i++) { if(a[i]=='(')i=work(i)+1; if(a[i]==')'){h[x].r=i;return i;} if(a[i]=='+')h[x].mi=min(h[x].mi,1); if(a[i]=='-')h[x].mi=min(h[x].mi,2); if(a[i]=='*')h[x].mi=min(h[x].mi,3); if(a[i]=='/')h[x].mi=min(h[x].mi,4); } h[x].r=l; return i; } int main() { scanf("%s",a+1); l=strlen(a+1); int i=work(0); for(i=2;i<=g;i++) { int x=h[i].l-1,y=h[i].r+1; int xma=0,yma=0; if(a[x]=='+')xma=max(xma,1); if(a[x]=='-')xma=max(xma,2); if(a[x]=='*')xma=max(xma,3); if(a[x]=='/')xma=max(xma,4); if(a[y]=='+')yma=max(yma,1); if(a[y]=='-')yma=max(yma,2); if(a[y]=='*')yma=max(yma,3); if(a[y]=='/')yma=max(yma,4); if(yma<=h[i].mi) { if((xma==2||xma==4)&&xma<h[i].mi) h[i].no=1; if((xma==1||xma==3||xma==0)&&xma<=h[i].mi) h[i].no=1; } } for(i=2;i<=g;i++) if(h[i].no) a[h[i].l]=a[h[i].r]=0; for(i=1;i<=l;i++) if(a[i]) printf("%c",a[i]); }```第二份AC,第一份错了,哪里催了 ``cpp
最新发布
09-29
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值