bzoj 2661: [BeiJing wc2012]连连看

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<algorithm>
  6 #define M 10000
  7 #define inf 2139062143
  8 using namespace std;
  9 int cnt=1,n,m,T,d[M],q[2*M],f[M],head[M],next[10*M],u[10*M],v[10*M],w[10*M],fro[10*M],fr[M];
 10 int ans,sum;
 11 void jia1(int a1,int a2,int a3,int a4)
 12 {
 13     cnt++;
 14     next[cnt]=head[a1];
 15     head[a1]=cnt;
 16     fro[cnt]=a1;
 17     u[cnt]=a2;
 18     v[cnt]=a3;
 19     w[cnt]=a4;
 20 }
 21 void jia(int a1,int a2,int a3,int a4)
 22 {
 23     jia1(a1,a2,a3,a4);
 24     jia1(a2,a1,0,-a4);
 25     return;
 26 }
 27 bool spfa()
 28 {
 29     memset(d,127,sizeof(int)*(T+1));
 30     d[0]=0;
 31     f[0]=1;
 32     q[1]=0;
 33     int h=0,t=1;
 34     for(;h<t;)
 35       {
 36         h++;
 37         int p=q[h];
 38         f[p]=0;
 39           for(int i=head[p];i;i=next[i])
 40           if(v[i]&&d[u[i]]>d[p]+w[i])
 41             {
 42                 d[u[i]]=d[p]+w[i];
 43                 fr[u[i]]=i;
 44                 if(!f[u[i]])
 45                   {
 46                     f[u[i]]=1;
 47                     t++;
 48                     q[t]=u[i];
 49                     }
 50             }
 51       }
 52     if(d[T]!=inf)
 53       return 1;
 54     return 0;
 55 }
 56 void mcf()
 57 {
 58     int mx=inf;
 59     for(int i=fr[T];i;i=fr[fro[i]])
 60       mx=min(mx,v[i]);
 61     for(int i=fr[T];i;i=fr[fro[i]])
 62       {
 63         v[i]-=mx;
 64         v[i^1]+=mx;
 65         ans+=mx*w[i];
 66       }
 67     sum+=mx;
 68     return;
 69 }
 70 int gcd(int a1,int a2)
 71 {
 72     int a3=a1%a2;
 73     for(;a3;)
 74       {
 75         a1=a2;
 76         a2=a3;
 77         a3=a1%a2;
 78       }
 79     return a2;
 80 }
 81 int main()
 82 {
 83     scanf("%d%d",&n,&m);
 84     T=2001;
 85     for(int i=n;i<=m;i++)
 86       {
 87         jia(0,i,1,0);
 88         jia(i+1000,T,1,0);
 89       }
 90     for(int i=n;i<=m;i++)
 91       for(int j=n;j<i;j++)
 92         {
 93             double a1=sqrt(i*i-j*j);
 94             int a2=floor(a1);
 95             if(a2==a1&&gcd(a2,j)==1)
 96               {
 97                 jia(i,j+1000,1,-i-j);
 98                 jia(j,i+1000,1,-i-j);
 99               }
100         }
101     for(;spfa();)
102       mcf();
103     printf("%d %d\n",sum/2,-ans/2);
104     return 0;
105 }

网络流如果满足条件,x向y‘连费用为z的边,y向x’连费用为z的边,最后除2便是答案。

你可能感兴趣的:(bzoj 2661: [BeiJing wc2012]连连看)