[BZOJ2661][BeiJing wc2012]连连看 费用流
2661: [BeiJing wc2012]连连看
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1349 Solved: 577
[Submit][Status][Discuss]
Description
凡是考智商的题里面总会有这么一种消除游戏。不过现在面对的这关连连看可不是QQ游戏里那种考眼力的游戏。我们的规则是,给出一个闭区间[a,b]中的全部整数,如果其中某两个数x,y(设x>y)的平方差x2-y2是一个完全平方数z2,并且y与z互质,那么就可以将x和y连起来并且将它们一起消除,同时得到x+y点分数。那么过关的要求就是,消除的数对尽可能多的前提下,得到足够的分数。快动手动笔算一算吧。
Input
只有一行,两个整数,分别表示a,b。
Output
两个数,可以消去的对数,及在此基础上能得到的最大分数。
Sample Input
1 15
Sample Output
2 34
HINT
对于30%的数据,1<=a,b<=100
对于100%的数据,1<=a,b<=1000
Source
拆点直接连边。跑最大费用最大流,答案/2。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<cstdio> 6 #include<algorithm> 7 using namespace std; 8 struct data { 9 int cost,w,to,next; 10 }e[100000]; 11 int head[10000],cnt; 12 int S,T; 13 void add(int u,int v,int w,int c) { 14 e[cnt].to=v;e[cnt].next=head[u];e[cnt].w=w;e[cnt].cost=c;head[u]=cnt++; 15 e[cnt].to=u;e[cnt].next=head[v];e[cnt].w=0;e[cnt].cost=-c;head[v]=cnt++; 16 } 17 int dis[10000]; 18 bool vis[10000]; 19 int q[10000],used; 20 bool spfa() { 21 memset(dis,-37,sizeof(dis)); 22 vis[T]=1;dis[T]=0; 23 int h=0,t=1; 24 q[0]=T; 25 while(h!=t) { 26 int now=q[h];h++;if(h==10000) h=0; 27 for(int i=head[now];i>=0;i=e[i].next) { 28 int to=e[i].to;if(!e[i^1].w) continue; 29 if(dis[to]<dis[now]-e[i^1].cost) { 30 dis[to]=dis[now]-e[i^1].cost; 31 if(!vis[to]) {vis[to]=1;q[t++]=to;if(t==10000)t=0;} 32 } 33 } 34 vis[now]=0; 35 } 36 used=-dis[S]; 37 return dis[S]!=dis[9999]; 38 } 39 int ans=0; 40 int dfs(int x,int a) { 41 if(x==T) {ans+=used*a;return a;} 42 int f=0,flow=0;vis[x]=1; 43 for(int i=head[x];i>=0;i=e[i].next) { 44 int to=e[i].to; 45 if(!vis[to]&&e[i].w>0&&dis[to]==dis[x]+e[i].cost&&(f=dfs(to,min(e[i].w,a)))) { 46 e[i].w-=f;e[i^1].w+=f; 47 a-=f;flow+=f; 48 if(a==0) break; 49 } 50 } 51 return flow; 52 } 53 void zkw() { 54 while(spfa()) { 55 do { 56 memset(vis,0,sizeof(vis)); 57 }while(dfs(S,2147483647)); 58 memset(vis,0,sizeof(vis)); 59 } 60 } 61 bool check(int x,int y) { 62 int tmp=x*x-y*y,z=(int)sqrt(tmp); 63 if (z*z!=tmp) return false; 64 if (y<z) swap(y,z); 65 while (z){tmp=y%z;y=z;z=tmp;} 66 return (y==1); 67 } 68 int main() { 69 memset(head,-1,sizeof(head)); 70 int a,b; 71 scanf("%d%d",&a,&b); 72 S=2001;T=2002; 73 for(int i=a;i<=b-1;i++) 74 for(int j=i+1;j<=b;j++) if (check(j,i)) { 75 add(i,j+1000,1,-i-j); 76 add(j,i+1000,1,-i-j); 77 } 78 for(int i=a;i<=b;i++) { 79 add(S,i,1,0); 80 add(i+1000,T,1,0); 81 } 82 zkw(); 83 int tot=0; 84 for(int i=0;i<cnt;i++) if (e[i].to==T&&!e[i].w) tot++; 85 printf("%d %d\n",tot/2,-ans/2); 86 }
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~