bzoj3158 千钧一发

14 篇文章 0 订阅

没错,最近在做网络流~这道题的确不错滴

最小割模型,偶数和奇数,一个连源点,一个连汇点

为什么?

1、偶数间明显符合第二个条件

2、奇数间,设一个为2n+1,另一个2m+1然后写一写就知道啦。

具体的可以看看hwzer的和硕哥的点击打开链接

注意好判平方的大小还有两个装置间的条件

贴个代码:

#include
   
   
    
    
#include
    
    
     
     
#include
     
     
      
      
#include
      
      
       
       
#include
       
       
         #include 
        
          #include 
         
           #define Max 0x7fffffff #define me(a,x) memset(a,x,sizeof a) using namespace std; typedef long long LL; struct node { int x,y,c,next; }a[5010000]; int len,first[1100]; void ins(int x,int y,int c) { a[++len].x=x,a[len].y=y,a[len].c=c; a[len].next=first[x],first[x]=len; a[++len].x=y,a[len].y=x,a[len].c=0; a[len].next=first[y],first[y]=len; } queue 
          
            q; int h[1010],t; bool spfa() { for(int i=0;i<=t;i++)h[i]=0; h[0]=1; q.push(0); while(!q.empty()) { int x=q.front(); q.pop(); for(int k=first[x];k;k=a[k].next) { int y=a[k].y; if(!h[y] && a[k].c) { h[y]=h[x]+1; q.push(y); } } } return h[t]>0; } int dfs(int x,int f) { if(x==t)return f; int de=0; for(int k=first[x];k;k=a[k].next) { int y=a[k].y; if(a[k].c && h[y]==h[x]+1) { int mf=dfs(y,min(a[k].c,f-de)); a[k].c-=mf,a[k^1].c+=mf,de+=mf; if(de==f)return f; } } if(!de)h[x]=0; return de; } int l[1010],p[1010]; int gcd(int x,int y) { if(y==0)return x; return gcd(y,x%y); } bool check(LL x,LL y) { LL c=(x*x)+(y*y),cc=sqrt(c); if(cc*cc!=c)return 0; if(gcd(x,y)>1)return 0; return 1; } int main() { int n,x,y,i,j; scanf("%d",&n); for(i=1;i<=n;i++)scanf("%d",&l[i]); for(i=1;i<=n;i++)scanf("%d",&p[i]); t=n+1; int s=0; len=1; me(first,0); for(i=1;i<=n;i++) { s+=p[i]; if(l[i]&1)ins(0,i,p[i]); else ins(i,t,p[i]); for(j=1;j<=n;j++) if( (l[i]&1)&& ((l[j]&1)==0) && check(l[i],l[j]) ) ins(i,j,Max); } while(spfa())s-=dfs(0,Max); printf("%d\n",s); return 0; } 
           
          
         
       
      
      
     
     
    
    
   
   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值