LightOJ

来源:互联网 发布:php tmp目录 编辑:程序博客网 时间:2024/06/06 01:22

原题地址:点击打开链接

题意:一个青蛙要从河的左边跳到右边,河中有许多的石头排在一条直线上,有大的石头可以踩无数次,而小的石头只能踩一次。

问你青蛙最少一次能跳多远才能从河的左边跳到右边,在从右边跳回左边。

思路:可用最大流求解,该题的难点在与建图,把每个石头看成是一个顶点,由于顶点上也有流量限制,所以要进行拆点,如果是

大石头就自身与自身建一条流量为2的点(因为只需要往返一次所以流量设为2即可),如果是小石头就自身与自身建一条流量为1的点,意思只能

经过一次,然后在用二分枚举出青蛙能跳的距离d,在判断每两个顶点之间的距离,如果小于d,则证明青蛙可以从这个石头跳向另一个石头,然后建

一条流量为2的边,别忘了源点与汇点之间也要建一条边.之前一直wa,半天没有找到原因,改了输入数据的方式之后突然就对了,,略坑。。

#include<stdio.h>#include<string.h>#include<vector>#define INF 1<<31-1#define min(x,y)(x<y?x:y)using namespace std;struct Edge{int to;int cap;int rev;};struct Point{int dis;int state;}p[210];vector<Edge>g[210];int used[210]; int left,right;void add_edge(int from,int to,int cap){g[from].push_back((Edge){to,cap,g[to].size()});g[to].push_back((Edge){from,0,g[from].size()-1});}int dfs(int u,int t,int f){if(u==t)  return f;  used[u]=1;for(int i=0;i<g[u].size();i++){Edge &e=g[u][i];int v=e.to;if(!used[v]&&e.cap>0){int d=dfs(v,t,min(e.cap,f));if(d>0){e.cap-=d;g[e.to][e.rev].cap+=d;return d;}}}return 0;}bool max_flow(int s,int t){int res=0;while(1){memset(used,0,sizeof(used));int d=dfs(s,t,INF);if(d<=0)break;res+=d;if(res>=2)break;}if(res>=2)                   //如果能走2次就没必要在继续判断了 return true;return false;}bool judge(Point p1,Point p2,int d)   //判断两个石头的距离是否小于能跳的最远距离 {int res=p1.dis-p2.dis;if(res<0) res=-res;if(res<=d)return true;return false;}void makeNew(int s,int t,int n,int d){int i,j;for(i=s;i<=t;i++)g[i].clear();for(i=1;i<=n;i++)            //拆点自身与自身建一条边,如果是大石头流量就2,否则1 {if(p[i].state==1){add_edge(i,i+n,2);}else{add_edge(i,i+n,1);}}for(i=1;i<=n;i++)for(j=1;j<=n;j++){if(i!=j&&judge(p[i],p[j],d))add_edge(i+n,j,2);}for(i=1;i<=n;i++){if(judge(p[s],p[i],d))add_edge(s,i,2);if(judge(p[t],p[i],d))add_edge(i+n,t,2);}if(judge(p[s],p[t],d))add_edge(s,t,2);}int solve(int s,int t,int n){while(left<right-1)            //用二分枚举每次能跳的最大的距离 {int mid=(left+right)/2;  makeNew(s,t,n,mid); if(max_flow(s,t)) right=mid;else left=mid;}return right;}int main(){int c,s,t,n,d,i,k=0,x;char ch;scanf("%d",&c);while(c--){scanf("%d%d",&n,&d);right=INF;left=0;s=0; t=n*2+1;p[s].dis=0;p[t].dis=d;for(i=1;i<=n;i++){scanf(" %c-%d",&ch,&x);if(ch=='B')p[i].state=1;elsep[i].state=0;p[i].dis=x;}int res=solve(s,t,n);printf("Case %d: %d\n",++k,res);}return 0;}/*31 10B-51 10S-52 10B-3 S-62 10*/ 


1 0
原创粉丝点击