码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1854: [Scoi2010]游戏 [连通分量 | 并查集 | 二分图匹配]

时间:2017-03-21 12:46:36      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:科学   cst   main   二分答案   text   题意   div   type   struct   

题意:

有$n \le 10^6$中物品,每种两个权值$\le 10^4$只能选一个,使得选出的所有权值从1递增,最大递增到多少


 

一开始想了一个奇怪的规定流量网络流+二分答案做法...然而我还不知道怎么规定流量...并且一定会T

然后发现题解中二分图匹配用了匈牙利,可以从小到大找增广路,貌似比较科学

然后发现还有用并查集的,看到“权值是点,装备是边”后突然灵机一动想到一个dfs做法

每个边的两个点可以选择一个

找出每个连通分量,如果里面有环或重边那么这里面所有点都可以选

如果是树的话,必须放弃一个点(当然是最大点),除非有的点在别的连通分量里选过了

$O(n)$,不带$\alpha$的啦,然而常数大所以并不比并查集快

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=1e4+5, M=1e6+5;
typedef long long ll;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<0||c>9){if(c==-)f=-1;c=getchar();}
    while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
    return x*f;
}

int n, m, u, v;
struct edge{int v, ne;} e[M<<1];
int cnt=1, h[N];
inline void ins(int u, int v) {
    e[++cnt]=(edge){v, h[u]}; h[u]=cnt;
    e[++cnt]=(edge){u, h[v]}; h[v]=cnt;
}
int vis[N], q[N], p, circle, flag[N];
int ve[M<<1];
void dfs(int u) {
    vis[u]=1; q[++p]=u;
    for(int i=h[u];i;i=e[i].ne) if(!ve[i]){
        ve[i] = ve[i^1] = 1;
        if(!vis[e[i].v]) dfs(e[i].v);
        else circle=1;
    }
}
int main() {
    freopen("in","r",stdin);
    m=read();
    for(int i=1; i<=m; i++) u=read(), v=read(), n=max(n, max(u, v)), ins(u, v);
    for(int i=1; i<=n; i++) if(!vis[i]) {
        p=0; circle=0; dfs(i);
        int mx=0;
        for(int i=1; i<=p; i++) {
            if(flag[q[i]]) circle = 1;
            else flag[q[i]] = 1;
            mx = max(mx, q[i]);
        } 
        if(!circle) flag[mx] = 0;
    }
    int ans = 0;
    while(flag[ans+1]) ans++;
    printf("%d",ans);
}

 

 

 

 

 

BZOJ 1854: [Scoi2010]游戏 [连通分量 | 并查集 | 二分图匹配]

标签:科学   cst   main   二分答案   text   题意   div   type   struct   

原文地址:http://www.cnblogs.com/candy99/p/6593525.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!