noip2010 关押罪犯 二分答案+二分图判断

来源:互联网 发布:maxdos 网络启动版 编辑:程序博客网 时间:2024/05/12 01:59

之前写过一个用虚点并查集做的,今天终于用二分ac了。


大体思路:

二分答案,小于mid的边忽略不计,如果不能构成二分图就要往大找让l=mid,如果可以就r=mid。

判断二分图要注意每次初始化color,可以用0和1也可以用1和2表示。从1到n循环,如果没有标记的就开始深搜,每次深搜把所有邻边染色。


其实还是参考了很多别人的代码...


一开始搞不明白标记的问题,后来终于想通,求最小值,如果ok的话要往下找,也就是r=mid,之前一直没转过弯来。


不知道为什么好多人每次二分都要重新构图,直接判断一下不就可以了吗?


http://blog.csdn.net/moon_sky1999/article/details/52744564?locationNum=2

这一篇还很好理解,只不过一层一层地往下堆代码有点吓人,在这个的基础上改了个dfs,下面贴代码


#include <algorithm>  #include <iostream>  #include <cstring>  #include <cstdlib>  #include <cstdio>  #include <vector>  using namespace std;  const int maxn=2e4+1;  const int inf=1e9;  int mid;bool ok;struct node{int t,w;};  vector<node> a[maxn];  int color[maxn]={0};  bool inq[maxn]={0};  void dfs(int x){if(ok==0)return; for(int j=0;j<a[x].size();j++){        int w=a[x][j].w; int t=a[x][j].t;                if(w<=mid) continue;if(color[t]==0){     color[t]=3-color[x];    dfs(t);}else if(color[t]==color[x]) {    ok=0;return;    }    }}int main()  {      ios::sync_with_stdio(false);      int n,m;cin>>n>>m;      int r=-inf,l=inf;      for(int i=1;i<=m;i++)      {          int x,y,z;          cin>>x>>y>>z;          node e;e.w=z;          e.t=y;a[x].push_back(e);          e.t=x;a[y].push_back(e);          l=min(z,l);          r=max(r,z);      }      if(l==r)l=0;      while(l<r)      {          mid=(l+r)/2;          memset(color,0,sizeof(color));          memset(inq,0,sizeof(inq));          ok=1;          for(int i=1;i<=n;i++)          {              if(color[i]==0)              {                  color[i]=1;                 dfs(i);             }              if(ok==0)break;         }          if(ok)r=mid;          else l=mid+1;      }      cout<<l;      return 0;  }  




0 0