6
24
2014
0

3158: 千钧一发

3158: 千钧一发

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 341  Solved: 139
[Submit][Status]

Description

 

Input

第一行一个正整数N。

第二行共包括N个正整数,第 个正整数表示Ai。

第三行共包括N个正整数,第 个正整数表示Bi。

 

Output

共一行,包括一个正整数,表示在合法的选择条件下,可以获得的能量值总和的最大值。

 

Sample Input



4
3 4 5 12
9 8 30 9
 

Sample Output


39
 
 
题面格式有点萎?
很容易看出是二分图最大独立集
但是要求权值最大的独立集……
看了好久题解……终于看懂了……
首先根据奇偶分成2个点集
奇数满足不存在ai2+aj2=T2
偶数满足gcd(ai,aj)>1
这个很好证对不对
考虑最小割,
连S→i,容量为bi(如果ai为奇数)
连j→T,容量为bj(如果aj为偶数)
对于ai,aj,如果不符合条件,则连一条ij,流量为Inf的边(保证不会被割)
如果有Si→j→T的边,表示i,j不能共存,要么割S→i(选择j),要么割j→T(选择i)
答案=Σb[i](1<=i<=n)-最小割
附上山哥的博客:
最后当然还有代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstdlib>
#include <set>
#define maxlongint 2147483647
#define maxn 10005
#define maxm 10000005
using namespace std;
int a[maxn],b[maxn],c,d,e,g,h,i,j,k,l,m,n,Ans,Dis[maxn],Flag,S,T,Tot;
int Way[maxm],Last[maxn],Next[maxm],Cost[maxm];
int min(int a,int b){if (a<b)return a;return b;}
void Spfa(){
     int Now,Head,Tail,Dl[maxn],Flag[maxn];
     memset(Dis,0x7f,sizeof(Dis));
     memset(Flag,0,sizeof(Flag));
     Head=1;Tail=1;Dis[S]=0;Dl[1]=S;
     for (;Head<=Tail;++Head){
         Now=Dl[Head];
         Flag[Now]=1;
         for (int i=Last[Now];i;i=Next[i])
         if ((Cost[i])&&(Dis[Way[i]]>Dis[Now]+1)){
                    Dis[Way[i]]=Dis[Now]+1;
                    if (!Flag[Way[i]]){Dl[++Tail]=Way[i];Flag[Way[i]]=1;}
             }
         }
     }
int dfs(int x,int Flow){
    if (Flow==0)return 0;
    if (x==T){Flag=1;return Flow;}
    int Sum=0,Tmp=0;
    for (int i=Last[x];i;i=Next[i])
    if (Dis[Way[i]]==Dis[x]+1){
                                  Tmp=dfs(Way[i],min(Flow-Sum,Cost[i]));
                                  Sum+=Tmp;
                                  Cost[i]-=Tmp;
                                  Cost[i^1]+=Tmp;
                                  if (Sum>=Flow)return Flow;
                                  }
       return Sum;
}
inline void make(int a,int b,int c){
	Way[++Tot]=b;
	Next[Tot]=Last[a];
	Last[a]=Tot;
	Cost[Tot]=c;
	Way[++Tot]=a;
	Next[Tot]=Last[b];
	Last[b]=Tot;
	Cost[Tot]=0;
}
int gcd(int a,int b){if (!b)return a;return gcd(b,a%b);}
int main(){
	Tot=1;
	scanf("%d",&n);S=n+1;T=n+2;
	for(i=1;i<=n;i++)scanf("%d",&a[i]);
	for(i=1;i<=n;i++){scanf("%d",&b[i]);m=m+b[i];}
	for(i=1;i<=n;i++)if (a[i]&1){
		make(S,i,b[i]);
	}else{
		make(i,T,b[i]);
	}
	for(i=1;i<=n;i++)if (a[i]&1)
	for(j=1;j<=n;j++)if (!(a[j]&1))
	if (gcd(a[i],a[j])==1){
		long long H=1ll*a[i]*a[i]+1ll*a[j]*a[j];
		double G=sqrt(H);
		long long HH=(long long)(G);
		if ((1ll*HH*HH==H))make(i,j,maxlongint);
	}
    Flag=1;
    for (;Flag;){
        Spfa();
        Flag=0;
        Ans+=dfs(S,maxlongint);
        }
    printf("%d\n",m-Ans);
    for(;;);
    return 0;
}
 
Category: BZOJ | Tags: | Read Count: 536

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com