zoukankan      html  css  js  c++  java
  • 「BalticOI 2015」拔河

    LOj

    显然题目可以转化为一个二分图。

    先找一下是否存在度数为(0)的点,存在则无解、

    然后把度数为(1)的点拎出来,这些点的选择是唯一的。

    这些可以用拓扑排序处理一下。

    接下来就剩下了一堆环。

    然后因为不能选择相邻的边,一个环内有两种选法,设为(A)(B)

    考虑先选出和比较小的那个,假设是(A),然后对(B-A)背包。

    因为权值范围比较小,所以可以把(01)背包转化为多重背包,然后就可以二进制拆分+(bitset)优化。

    然后只要判断([-k,k])能否凑出来就行了。

    复杂度貌似是(frac{ksqrt{k}log k}{64})

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<queue>
    #include<set>
    #include<bitset>
    #include<map>
    using namespace std;
    #define rg register
    void read(int &x){
        char ch;bool ok;
        for(ok=0,ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')ok=1;
        for(x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());if(ok)x=-x;
    }
    const int maxn=2e5+10;queue<int>qq;
    map<int,int>mp;
    int sum,n,m,k,w,in[maxn],q[maxn],tot,s[maxn],t,num[maxn];bool vis[maxn];
    struct oo{int l,r,x;}a[maxn];
    int cnt,pre[maxn*2],nxt[maxn*2],h[maxn],v[maxn*2];
    bitset<maxn*30>f;
    void add(int x,int y,int z){
        pre[++cnt]=y,nxt[cnt]=h[x],h[x]=cnt,v[cnt]=z;
        pre[++cnt]=x,nxt[cnt]=h[y],h[y]=cnt,v[cnt]=z;
    }
    void topsort(){
        for(rg int i=1;i<=n*2;i++)if(in[i]==1)qq.push(i);
        while(!qq.empty()){
    	int x=qq.front();qq.pop();vis[x]=1;
    	for(rg int i=h[x];i;i=nxt[i])
    	    if(!vis[pre[i]]){
    		in[pre[i]]--;
    		if(in[pre[i]]==1)qq.push(pre[i]);
    		if(x>n)sum+=v[i];
    	}
        }
        for(rg int i=1;i<=n*2;i++)
    	if(!vis[i]){
    	    tot=0;int l=i;
    	    while(!vis[l]){
    		vis[l]=1;
    		for(rg int j=h[l];j;j=nxt[j])if(!vis[pre[j]])l=pre[j],q[++tot]=v[j];
    	    }
    	    int x=0,y=0;
    	    for(rg int j=1;j<=tot;j+=2)x+=q[j];
    	    for(rg int j=2;j<=tot;j+=2)y+=q[j];
    	    if(x>y)swap(x,y);sum+=x;
    	    if(!mp[y-x])mp[y-x]=++t,s[t]=y-x;
    	    num[mp[y-x]]++;
    	}
    }
    int main(){
        read(n),read(k);w=n;n<<=1;
        for(rg int i=1;i<=n;i++){
    	read(a[i].l),read(a[i].r),read(a[i].x);a[i].l+=n,a[i].r+=n+w;
    	in[a[i].l]++,in[a[i].r]++;in[i]=2;
    	add(i,a[i].l,a[i].x),add(i,a[i].r,-a[i].x);
        }
        for(rg int i=n+1;i<=n*2;i++)
    	if(!in[i])return puts("NO"),0;
        topsort();f[0]=1;
        for(rg int i=1;i<=t;i++){
    	for(rg int j=1;j<num[i];j<<=1)
    	    f|=f<<(s[i]*j),num[i]-=j;
    	f|=f<<(s[i]*num[i]);
        }
        for(rg int i=-k;i<=k;i++)
    	if(sum<=i&&f[i-sum])return puts("YES"),0;
        puts("NO");
    }
    
    
  • 相关阅读:
    vue store状态存储管理
    Git分支管理
    oracle事务不能回滚的原因
    vue教程(四)--其他实用用法补充
    vue教程(三)-slotkeep-alive的使用
    vue教程(二)--过滤器和监视改动功能
    vue教程(一)-html使用vue
    Linux后台命令导入MySQL语句
    CentOS6下的ElasticSearch运行步骤
    浅谈JAVA代码优化
  • 原文地址:https://www.cnblogs.com/lcxer/p/11852114.html
Copyright © 2011-2022 走看看