zoukankan      html  css  js  c++  java
  • noip 2010 关押罪犯 (二分图染色 并茶几)

    
    
    /*
    二分图染色版本
    两个监狱对应二部图的两部分 
    在给定的怨气值里二分 
    对于每一个Ci 进行染色判断是否合法 
    染色的时候 如果这条边的ci > Ci 这两个人就带分开 即染成不同的颜色
    如果染色到某两个点颜色相同且怨气值>Ci 这个Ci就不合法
    二分直到最后答案 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 100010
    using namespace std;
    int n,m,num,head[maxn],Ci,ans,color[maxn];
    struct node
    {
        int v,t,pre;
    }e[maxn*2];
    struct nope
    {
        int x,y,z;
    }p[maxn];
    int cmp(const nope &a,const nope &b)
    {
        return a.z<b.z;
    }
    void Add(int from,int to,int dis)
    {
        num++;
        e[num].t=dis;
        e[num].v=to;
        e[num].pre=head[from];
        head[from]=num;
    }
    bool Color(int s)
    {
        for(int i=head[s];i;i=e[i].pre)
          if(e[i].t>Ci)
              {
                if(color[s]==color[e[i].v])return 0;
                if(color[e[i].v]==0)
                    {
                      color[e[i].v]=3-color[s];
                      if(!Color(e[i].v))return 0;
                }
            }
        return 1;
    }
    bool pd()
    {
        for(int i=1;i<=n;i++)
          if(color[i]==0)
            {
              color[i]=1;
              if(!Color(i))return 0;
            }
        return 1;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        int u,v,t;
        for(int i=1;i<=m;i++)
          {
              scanf("%d%d%d",&u,&v,&t);
              p[i].x=u;p[i].y=v;p[i].z=t;
              Add(u,v,t);Add(v,u,t);
          }
        sort(p+1,p+1+m,cmp);
        int l=0,r=m;
        while(l<=r)
          {
              memset(color,0,sizeof(color));
              int mid=(l+r)/2;
              Ci=p[mid].z;
              if(pd())
                {
                    r=mid-1;
                    ans=Ci;
              }
            else l=mid+1;
          }
        printf("%d
    ",ans);
        return 0;
    }
    
    
    
     
    /*
    并茶几版本
    因为就有两个监狱 两个人要么一个监狱 要么不一个监狱(废话- - )
    为了使ans最小 我们一定会让ci大的组合先分开
    所以按ci排一遍序 然后for每一对
    如果发现他俩在一个集合 输出ci结束
    否则的话 我们希望的是把他两个分开
    即把他们分别跟对方的仇人合并 
    所以我们假设每个人的仇人都是i+n 
    对于i 如果另外两个人都合并到了i+n 说明两个人一定在一所监狱 
    */
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define maxx 40010
    #define maxn 200010
    using namespace std;
    int fa[maxx],n,m;
    struct node
    {
        int a;
        int b;
        int c;
    }s[maxn];
    int cmp(const node &x,const node &y)
    {
        return x.c>y.c;
    }
    int find(int x)
    {
        if(x!=fa[x])fa[x]=find(fa[x]);
        return fa[x];
    }
    int main()
    {
        int i,j;
        cin>>n>>m;
        for(i=1;i<=n*2;i++)fa[i]=i;
        for(i=1;i<=m;i++)
          cin>>s[i].a>>s[i].b>>s[i].c;
        sort(s+1,s+1+m,cmp);
        for(i=1;i<=m;i++)
          {
              int r1=find(s[i].a);
              int r2=find(s[i].b);
              if(r1==r2)
                {
                    cout<<s[i].c;
                    return 0;
              }
            fa[r1]=find(s[i].b+n);
            fa[r2]=find(s[i].a+n);
          }
        cout<<0;
        return 0;
    }
  • 相关阅读:
    您还在用下一步下一步的方式安装SQLSERVER和SQLSERVER补丁吗?
    SQLSERVER误删除了Windows登录用户验证方式使用Windows身份验证的解决方法
    批量解密SQLSERVER数据库中的各种对象的工具dbForge SQL Decryptor
    SQLSERVER将数据移到另一个文件组之后清空文件组并删除文件组
    SQLSERVER群集故障转移笔记
    兼容,原来在这里就已经開始--------Day34
    Objective-C的对象模型和runtime机制
    CF B. Kolya and Tandem Repeat
    循环队列的实现
    LintCode 子树
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/5547680.html
Copyright © 2011-2022 走看看