多校第十场HRBEU&&HDU 3931Cross the Fire(最小权点割+拆点+BT构图思想)
来源:互联网 发布:查看win7开放的端口 编辑:程序博客网 时间:2024/06/08 19:15
题意:一个hero要超越雷区,hero有一定的血,触雷要掉一定血,雷是已知半径和杀伤力的,求hero能否活着穿过雷区,且耗费最少的血;
题解:我们将所有的圆映射成无向图上的点,并且把任意两个相交的圆(包括相切和包含)之间连上一条无向边;将上边界当成逻辑源点,下边界当成逻辑汇点,所有与之相交的圆都分别向它们连上一条有向边。
模型抽象为若存在一条从源点到汇点的独立轨,则人必须触一次雷,而人想通过街道,意味着要破坏这些独立轨,使得源点和汇点之间失去连通性。
这个显然是一个无向图的最小权点割问题了。
将除了源汇点之外的内点全部拆点,原来的点权转化为边容量,其它边的边容量为正无穷,接着从源点向汇点压流。
最后比较一下最大流值和人的初始体力值即是最后的答案。
网络流的重点是构图,看了图解之后,直接敲完就AC了。
#include <cstdio>#include <cstring>const int maxN=255;const int maxn=550;const int inf=1<<25;const int s=0;int L , W , N , P;struct edge{ int v,next,w;}edge[maxn*maxn];int head[maxn],cnt;//for sap void addedge(int u, int v, int w){ edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].v=u; edge[cnt].w=0; edge[cnt].next=head[v]; head[v]=cnt++;}int sap(int t){ int pre[maxn],cur[maxn],dis[maxn],gap[maxn]; int flow=0 , aug=inf ,u; bool flag; for (int i=0 ; i<=t ; ++i) { cur[i]=head[i]; gap[i]=dis[i]=0; } gap[s]=t+1; u=pre[s]=s; while (dis[s]<=t) { flag=0 ; for (int &j=cur[u] ; ~j ; j=edge[j].next) { int v=edge[j].v; if (edge[j].w>0 && dis[u]==dis[v]+1) { flag=1; if(edge[j].w<aug)aug=edge[j].w; pre[v]=u; u=v; if (u==t) { flow+=aug; while (u!=s) { u=pre[u]; edge[cur[u]].w-=aug; edge[cur[u]^1].w+=aug; } aug=inf; } break; } } if (flag)continue ; int mindis=t+1; for (int j=head[u]; ~j ; j=edge[j].next) { int v=edge[j].v; if (edge[j].w>0 && dis[v]<mindis) { mindis=dis[v]; cur[u]=j; } } if(--gap[dis[u]]==0)break; gap[dis[u]=mindis+1]++; u=pre[u]; } return flow;}int x[maxN],y[maxN],r[maxN],p[maxN];//for build graphbool intersect (int a,int b){ int dis=(x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]); if(dis<=((r[a]+r[b])*(r[a]+r[b])))return true ; else return false ;}void build_graph(){ int n=2*N; for (int i=1 ; i<=N ; ++i) { addedge (i,i+N,p[i]); if(y[i]<=r[i])addedge(0,i,inf); if(y[i]+r[i]>=W)addedge(i+N,n+1,inf); for (int j=i+1 ; j<=N ; ++j)// if(intersect(i,j))addedge(i+N,j,inf),addedge(j+N,i,inf); }}void init (){ memset (head , -1 , sizeof(head)); cnt=0;}int main (){ while (~scanf("%d%d%d%d",&L,&W,&N,&P)) { init(); for (int i=1 ; i<=N ; ++i) scanf("%d %d %d %d",x+i,y+i,r+i,p+i); build_graph(); int ans=P-sap(2*N+1); if(ans<0)printf("Our hero has been killed\n"); else printf("%d\n",ans); } return 0;}
- 多校第十场HRBEU&&HDU 3931Cross the Fire(最小权点割+拆点+BT构图思想)
- hdu 3931 Cross the Fire
- hdu 3931 Cross the Fire
- 多校第十场HRBEU &&hdu 3932 Groundhog Build Home(模拟退火算法)
- 2017 多校训练第十场 HDU 6178 Monkeys 最小点覆盖+树形DP
- HDU 3861--The King’s Problem【scc缩点构图 && 二分匹配求最小路径覆盖】
- POJ 3686 The Windy's (二分图最小权匹配 拆点 构图)
- hdu 4705 Y 多校第十场
- hdu 4704 Sum 多校第十场
- hdu 4696 Answers 多校第十场
- hdu 1045 Fire Net (最小点覆盖)
- 多校第十场
- hdu 4699 Editor 多校第十场 (模拟)
- HDU 4710 Game(多校第十场)
- 多校第十场:HDU 4973 树状数组+前缀+二分
- hdu 5862 Counting Intersections多校第十场
- hdu 6181 Two Paths (多校第十场)
- HDU 6178 Monkeys(树上DP 17多校第十场)
- c++中new的用法
- OO设计的接口分隔原则
- C#索引器
- POJ1080 Human Gene Functions DP
- helloPe的android项目实战之连连看—实现篇(二)
- 多校第十场HRBEU&&HDU 3931Cross the Fire(最小权点割+拆点+BT构图思想)
- 手把手教你TestComplete_EXCEL操作示例
- OO设计的依赖倒置原则
- SharpDev学习
- MFC脚印_Frame
- pku 1159 dp
- 基于Lucene的搜索系统 同时使用Paoding进行中文分词 二
- 手把手教你TestComplete_数据库操作函数示例
- TestComplete中文帮助手册.pdf