bzoj3275:最小割

看了师兄的建图方法,然后YY一下懂了一点?=>建图后即是求最小割,也就是说求最少去掉几条边就能使图不连通,图不连通意味着不会有两个相互矛盾的节点存在,若能联通的话会有两个相互矛盾的节点能够同时存在,所以=>("

S->每个奇数,每个偶数->T各连一条边, 容量为这个数字.然后不能同时选的两个数连容量为+oo的边. 总数-最大流即是答案.

因为满足a2+b2=c2的a,b一定是一奇一偶或者两个偶数, 2偶不满足gcd=1, 所以两个数不能同时选一定是一奇一偶.")

以上引自sj师兄。两个奇数证明一下不难得出。

然后又是错了一个地方然后。。还有判断a*a+b*b=c*c不会判断,orz。

---------------------------------------------------------------------------------------

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
#define clr(x,c) memset(x,c,sizeof(x))
#define ll long long
const int inf=0x3f3f3f3f;
int read(){
 int x=0,f=1;char c=getchar();
 while(!isdigit(c)){
  if(c==‘-‘) f=-1;
  c=getchar();
 }
 while(isdigit(c)){
  x=x*10+c-‘0‘;
  c=getchar();
 }
 return x*f;
}

struct edge{
 int to,cap;
 edge *next,*rev;
};
edge e[400000],*cur[3005],*head[3005],*p[3005],*pt;
int d[3005],cnt[3005],a[3005];
void add(int u,int v,int d){
 pt->to=v;
 pt->cap=d;
 pt->next=head[u];
 head[u]=pt++;
}
void adde(int u,int v,int d){
 add(u,v,d);add(v,u,0);
 head[u]->rev=head[v];
 head[v]->rev=head[u];
}

int gcd(int x,int y){
 return y?gcd(y,x%y):x;
}
bool pd(int x,int y){
 if(gcd(x,y)!=1) return false;
 ll tmp=(ll)x*x+(ll)y*y;
 ll t=sqrt(tmp);
 if(tmp==t*t) return true;
 return false;
}

int maxflow(int s,int t,int n){
 int flow=0,a=inf,x=s;
 clr(cnt,0);
 clr(d,0);cnt[0]=n;
 while(d[s]<n){
  edge *ee;
  for(ee=cur[x];ee;ee=ee->next){
   if(ee->cap>0&&d[ee->to]==d[x]-1)
     break;
  }
  if(ee){
   a=min(a,ee->cap);
   cur[x]=p[ee->to]=ee;
   x=ee->to;
   if(x==t){
    while(x!=s){
     p[x]->cap-=a;
     p[x]->rev->cap+=a;
     x=p[x]->rev->to;
    }
    flow+=a;
    a=inf;
   }
  }
  else{
   if(--cnt[d[x]]==0) break;  //又是这里又是这里
   d[x]=n;
   for(ee=head[x];ee;ee=ee->next){
    if(ee->cap>0&&d[ee->to]+1<d[x]){
     d[x]=d[ee->to]+1;
     cur[x]=ee;
    }
   }
   cnt[d[x]]++;
   if(x!=s) x=p[x]->rev->to;
  }
 }
 return flow;
}

int main(){
 int n=read(),s=0,t=n+1,tot=t+1,ans=0;
 pt=e;
 rep(i,n){
  a[i]=read();ans+=a[i];
  a[i]%2?adde(s,i,a[i]):adde(i,t,a[i]);
 }
 rep(i,n)
     if(a[i]%2)
        rep(j,n)
           if(a[j]%2==0&&pd(a[i],a[j]))
            adde(i,j,inf);
 printf("%d\n",ans-maxflow(s,t,tot));
 return 0;
}

---------------------------------------------------------------------------------------

3275: Number

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 561  Solved: 249
[Submit][Status][Discuss]

Description

有N个正整数,需要从中选出一些数,使这些数的和最大。
若两个数a,b同时满足以下条件,则a,b不能同时被选
1:存在正整数C,使a*a+b*b=c*c
2:gcd(a,b)=1

Input

第一行一个正整数n,表示数的个数。

第二行n个正整数a1,a2,?an。

Output

最大的和。

Sample Input

5
3 4 5 6 7

Sample Output

22

HINT

n<=3000。

Source

网络流

[Submit][Status][Discuss]

HOME Back

时间: 2024-10-11 13:07:34

bzoj3275:最小割的相关文章

【BZOJ-3275&amp;3158】Number&amp;千钧一发 最小割

3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 748  Solved: 316[Submit][Status][Discuss] Description 有N个正整数,需要从中选出一些数,使这些数的和最大.若两个数a,b同时满足以下条件,则a,b不能同时被选1:存在正整数C,使a*a+b*b=c*c2:gcd(a,b)=1 Input 第一行一个正整数n,表示数的个数. 第二行n个正整数a1,a2,?an. Output

【最小割】【Dinic】bzoj3275 Number

每个点拆点,分别向源/汇连a[i]的边,满足条件的相互连INF的边,答案为sum-maxflow*2. 因为若有几个点不能同时被选,我们要贪心地选择其中和尽量大的部分,这可以由最小割来保证. #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> using namespace std; #define INF 214748364

二分图&amp;网络流&amp;最小割等问题的总结

二分图基础: 最大匹配:匈牙利算法 最小点覆盖=最大匹配 最小边覆盖=总节点数-最大匹配 最大独立集=点数-最大匹配 网络流: 带下界网络流 最小割问题的总结: *意义 1.加inf的边表示不能被割,通常用于体现某个点必须属于某个集合 连边(s,u,w)代表如果u不在s割的话需要付出代价w 2.连边(u,v,w)代表如果u在s割,v在t割需要付出代价w 但注意,如果u在t割,v在s割是不需要付出代价的. 那么如果连边(u,v,w)以及(v,u,w)则说明当u与v所属割不同的时候需要付出代价w *

【BZOJ2039】【2009国家集训队】人员雇佣 [最小割]

人员雇佣 Time Limit: 20 Sec  Memory Limit: 259 MB[Submit][Status][Discuss] Description 作为一个富有经营头脑的富翁,小L决定从本国最优秀的经理中雇佣一些来经营自己的公司.这些经理相互之间合作有一个贡献指数,(我们用Ei,j表示i经理对j经理的了解程度),即当经理i和经理j同时被雇佣时,经理i会对经理j做出贡献,使得所赚得的利润增加Ei,j.当然,雇佣每一个经理都需要花费一定的金钱Ai,对于一些经理可能他做出的贡献不值得

hdoj 4289 Control 【拆点 求最小割】

Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2295    Accepted Submission(s): 961 Problem Description You, the head of Department of Security, recently received a top-secret informati

There is a war (hdu 2435 最小割+枚举)

There is a war Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 970    Accepted Submission(s): 277 Problem Description There is a sea. There are N islands in the sea. There are some directional

HDU 3657 Game(取数 最小割)经典

Game Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1065    Accepted Submission(s): 449 Problem Description onmylove has invented a game on n × m grids. There is one positive integer on each g

POJ2914 Minimum Cut【全局最小割】【Stoer-Wangner】

题目链接: http://poj.org/problem?id=2914 题目大意: 提一个无向有重边的图,有重边的边权累加起来,求全局最小割. 思路: 一个无向连通图,去掉一个边集可以使其变成两个连通分量则这个边集就是割集.最小割 集当然就是权和最小的割集. 这是一个最简单的全局最小割模板题.直接套上模板就可以了.来说说Stoer-Wangner算 法吧. Stoer-Wangner算法: 对于图中的任意两个顶点u和v,若u,v属于最小割的同一个集合中,那么僵顶点u和顶点 v合并后并不影响图的

HDU 3035 War(对偶图求最小割)

HDU 3035 War 题目链接 题意:根据图那样,给定一个网络,要求阻断s到t,需要炸边的最小代价 思路:显然的最小割,但是也显然的直接建图强行网络流会超时,这题要利用平面图求最小割的方法,把每一块当成一个点,共有边连边,然后每一个路径就是一个割,然后最短路就是最小割了 代码: #include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace s