BZOJ3275: Number

来源:互联网 发布:音乐cd刻录软件 编辑:程序博客网 时间:2024/06/05 15:13

思路:
像这种题做过好几道了。首先限制条件一定是最小割解决。然后奇数不满足条件一,偶数不满足条件二。这样就可以转化成二分图了。

/**************************************************************    Problem: 3275    User: DtenSherlock    Language: C++    Result: Accepted    Time:3460 ms    Memory:24808 kb****************************************************************/#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>#include<cmath>#include<cstring>#include<string>#include<queue>using namespace std;const int imax=3000+229; const int dmax=imax*2;const int bmax=2000000+229;const int inf=100000229;int n,sum;int a[imax],id[imax],num1,num2;int S,T,num,head[dmax],to[bmax],inext[bmax],re[bmax];void iread(){    scanf("%d",&n);    for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum+=a[i];}bool pd(int x,int y){    int t=(int)(sqrt(x*x+y*y));    if(__gcd(x,y)==1 && t*t==x*x+y*y) return 1;    return 0;}void iadd(int u,int v,int flow){    to[num]=v; re[num]=flow; inext[num]=head[u]; head[u]=num++; }void add(int u,int v,int flow){ iadd(u,v,flow); iadd(v,u,0);}void build(){    S=0; T=n+n+1;    memset(head,-1,sizeof(head));    for(int i=1;i<=n;i++)    {        if(a[i]&1)        {            id[i]=++num1;            add(S,id[i],a[i]);          }           else        {            id[i]=++num2;            add(id[i]+n,T,a[i]);            }    }       for(int i=1;i<=n;i++)        if(a[i]&1)            for(int j=1;j<=n;j++)            {                if((a[j]&1)==0 && pd(a[i],a[j]))                     add(id[i],n+id[j],inf);            }}queue<int> q;bool vis[dmax]; int d[dmax];bool BFS(){    memset(d,0,sizeof(d));    vis[S]=1; q.push(S); d[S]=1;    while(!q.empty())    {        int u=q.front(); q.pop();        vis[u]=false;        for(int i=head[u];i!=-1;i=inext[i])             if(re[i] && !d[to[i]])            {                d[to[i]]=d[u]+1;                if(!vis[to[i]]) q.push(to[i]),vis[to[i]]=1;             }    }     return d[T]!=0;}int DFS(int x,int c){    if(x==T || c==0) return c;    int r=c;    for(int i=head[x];i!=-1;i=inext[i])        if(re[i] && d[to[i]]==d[x]+1)        {            int f=DFS(to[i],min(re[i],r));              r-=f; re[i]-=f; re[i^1]+=f;            if(!r) break;        }    if(r==c) d[x]=0;    return c-r;}void iwork(){    build();    int ans=0;    while(BFS()) ans+=DFS(S,inf);    printf("%d\n",sum-ans);}int main(){    iread();    iwork();    return 0;}
0 0