zoukankan      html  css  js  c++  java
  • 【bzoj3158】 千钧一发

    http://www.lydsy.com/JudgeOnline/problem.php?id=3158 (题目链接)

    题意

      给出n个装置,每个装置i有一个特征值a[i]和一个能量值b[i],要求选出能量值和尽可能大的装置,使它们两两之间至少满足一下两条件中的1个条件:1.不存在T,a[i]*a[i]+a[j]*a[j]=T*T;2.gcd(a[i],a[j])>1。

    Solution

      通过观察与思考,我们可以发现,如果把不符合条件的两个装置用边连接起来,最后要求的就是带权最大独立集,然而这是一般图,难道还要去写最大团?这是不现实的,考虑它是否满足二分图的性质。

      写写画画以后,发现:

        对于两个偶数来说,它们之间的gcd至少为2,也就是满足第二个条件,任意两个偶数之间都没有边相连。

        对于两个奇数来说,它们的平方和$=2*(2a^2+2b^2+2a+2b+1)$,偶数*奇数,一定满足条件1,任意两个奇数之间都没有边相连。

      于是这就是个二分图了,奇数放左边,偶数放右边,然后最小割求二分图带权最大独立集。

    细节

      sqrt出来放到一个LL里面。。。如果放在一个double中,那么就不是正整数T了。。。难怪一直0ms Wa。。

    代码

    // bzoj3158
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #define LL long long
    #define inf 2147483640
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
    using namespace std;
    
    const int maxn=1010;
    struct edge {int to,next,w;}e[maxn*maxn*2];
    int head[maxn],d[maxn];
    LL a[maxn],b[maxn];
    int cnt=1,n,m,es,et,ans;
    
    int gcd(int a,int b) {return b==0 ? a : gcd(b,a%b);}
    void link(int u,int v,int w) {
    	e[++cnt]=(edge){v,head[u],w};head[u]=cnt;
    	e[++cnt]=(edge){u,head[v],0};head[v]=cnt;
    }
    bool bfs() {
    	memset(d,-1,sizeof(d));
    	queue<int> q;q.push(es);d[es]=0;
    	while (!q.empty()) {
    		int x=q.front();q.pop();
    		for (int i=head[x];i;i=e[i].next) if (e[i].w && d[e[i].to]<0) {
    				d[e[i].to]=d[x]+1;
    				q.push(e[i].to);
    			}
    	}
    	return d[et]>0;
    }
    int dfs(int x,int f) {
    	if (x==et || f==0) return f;
    	int used=0,w;
    	for (int i=head[x];i;i=e[i].next) if (e[i].w && d[e[i].to]==d[x]+1) {
    			w=dfs(e[i].to,min(e[i].w,f-used));
    			e[i].w-=w;e[i^1].w+=w;
    			used+=w;if (used==f) return used;
    		}
    	if (!used) d[x]=-1;
    	return used;
    }
    void Dinic() {while (bfs()) ans-=dfs(es,inf);}
    int main() {
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
    	for (int i=1;i<=n;i++) scanf("%lld",&b[i]),ans+=b[i];
    	es=n+1;et=n+2;
    	for (int i=1;i<=n;i++) {
    		if (a[i]%2==1) link(es,i,b[i]);
    		else link(i,et,b[i]);
    	}
    	for (int i=1;i<=n;i++) {
    		if (a[i]%2==0) continue;
    		for (int j=1;j<=n;j++) if (a[j]%2==0) {
    				if (gcd(a[i],a[j])!=1) continue;
    				LL x=sqrt(a[i]*a[i]+a[j]*a[j]);
    				if (x*x!=a[i]*a[i]+a[j]*a[j]) continue;
    				link(i,j,inf);
    			}
    	}
    	Dinic();
    	printf("%d",ans);
        return 0;
    }
    

      

  • 相关阅读:
    Day10
    Day9
    Day8
    Day 7
    Day-6
    java中的原子性
    java 原子性
    内存可见性
    JVM 常忘笔记
    JVM 解释执行 编译执行 JIT
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6201375.html
Copyright © 2011-2022 走看看