loj 1154(最大流+枚举汇点)
来源:互联网 发布:兔子白网络 编辑:程序博客网 时间:2024/05/22 06:53
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26868
思路:拆点,容量为最多能跳的步数,然后设立一个超级源点,源点与各点两连边,容量为一开始的企鹅数,最后就是枚举汇点了,跑最大流验证即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<cmath> 7 using namespace std; 8 #define MAXN 222 9 #define MAXM 222222 10 #define inf 1<<30 11 #define FILL(a,b) memset(a,b,sizeof(a)) 12 13 struct Edge{ 14 int v,cap,next; 15 }edge[MAXM]; 16 17 int n,vs,vt,NV,NE,head[MAXN]; 18 double d; 19 20 21 void Insert(int u,int v,int cap) 22 { 23 edge[NE].v=v; 24 edge[NE].cap=cap; 25 edge[NE].next=head[u]; 26 head[u]=NE++; 27 28 edge[NE].v=u; 29 edge[NE].cap=0; 30 edge[NE].next=head[v]; 31 head[v]=NE++; 32 } 33 34 int level[MAXN],gap[MAXN]; 35 void bfs(int vt) 36 { 37 FILL(level,-1); 38 FILL(gap,0); 39 queue<int>que; 40 que.push(vt); 41 level[vt]=0; 42 gap[0]++; 43 while(!que.empty()){ 44 int u=que.front(); 45 que.pop(); 46 for(int i=head[u];i!=-1;i=edge[i].next){ 47 int v=edge[i].v; 48 if(level[v]!=-1)continue; 49 level[v]=level[u]+1; 50 gap[level[v]]++; 51 que.push(v); 52 } 53 } 54 } 55 56 int pre[MAXN],cur[MAXN]; 57 int SAP(int vs,int vt) 58 { 59 bfs(vt); 60 memcpy(cur,head,sizeof(head)); 61 int u=pre[vs]=vs,aug=inf,maxflow=0; 62 gap[0]=NV; 63 while(level[vs]<NV){ 64 bool flag=false; 65 for(int &i=cur[u];i!=-1;i=edge[i].next){ 66 int v=edge[i].v; 67 if(edge[i].cap>0&&level[u]==level[v]+1){ 68 flag=true; 69 aug=min(aug,edge[i].cap); 70 pre[v]=u; 71 u=v; 72 if(v==vt){ 73 maxflow+=aug; 74 for(u=pre[u];v!=vs;v=u,u=pre[u]){ 75 edge[cur[u]].cap-=aug; 76 edge[cur[u]^1].cap+=aug; 77 } 78 aug=inf; 79 } 80 break; 81 } 82 } 83 if(flag)continue; 84 int minlevel=NV; 85 for(int i=head[u];i!=-1;i=edge[i].next){ 86 int v=edge[i].v; 87 if(edge[i].cap>0&&level[v]<minlevel){ 88 cur[u]=i; 89 minlevel=level[v]; 90 } 91 } 92 if(--gap[level[u]]==0)break; 93 level[u]=minlevel+1; 94 gap[level[u]]++; 95 u=pre[u]; 96 } 97 return maxflow; 98 } 99 100 struct Node{101 double x,y;102 int num,step;103 }node[MAXN];104 105 double Get_Dist(int i,int j)106 {107 double d1=(node[i].x-node[j].x)*(node[i].x-node[j].x);108 double d2=(node[i].y-node[j].y)*(node[i].y-node[j].y);109 return sqrt(d1+d2);110 }111 112 void Build(int ed)113 {114 NE=0;115 FILL(head,-1);116 vs=0,vt=2*n+1;117 NV=vt+1;118 for(int i=1;i<=n;i++){119 Insert(i,i+n,node[i].step);120 Insert(vs,i,node[i].num);121 }122 for(int i=1;i<=n;i++){123 for(int j=i+1;j<=n;j++){124 if(Get_Dist(i,j)<=d){125 Insert(i+n,j,inf);126 Insert(j+n,i,inf);127 }128 }129 }130 Insert(ed,vt,inf);131 }132 133 int main()134 {135 int _case,ans,sum,flag,t=1;136 scanf("%d",&_case);137 while(_case--){138 scanf("%d%lf",&n,&d);139 sum=0;140 for(int i=1;i<=n;i++){141 scanf("%lf%lf%d%d",&node[i].x,&node[i].y,&node[i].num,&node[i].step);142 sum+=node[i].num;143 }144 flag=0;145 printf("Case %d:",t++);146 //枚举集中点147 for(int i=1;i<=n;i++){148 Build(i);149 if(SAP(vs,vt)==sum)flag=1,printf(" %d",i-1);150 }151 if(!flag)printf(" -1");152 puts("");153 }154 return 0;155 }
0 0
- loj 1154(最大流+枚举汇点)
- poj 3498 (最大流,枚举汇点)
- LOJ#101最大流
- loj 1155(最大流)
- poj 3498(枚举汇点的最大流)
- loj 1156(二分+最大流)
- loj 1167(二分+最大流)
- LOJ #116. 有源汇有上下界最大流
- 【loj】#6007. 「网络流 24 题」方格取数(二分图最大点权独立集)
- LOJ #6006. 试题库 (简单最大流+输出可行路径)
- 【HDU1281】【最大匹配】【取点枚举】
- hdu4309枚举+最大流
- poj 2391 Ombrophobic Bovines(二分枚举+floyd+最大流+拆点)
- 【loj】#6005. 「网络流 24 题」最长递增子序列(dp+最大流)
- loj #6004. 「网络流 24 题」圆桌聚餐(最大流)
- loj 1150(spfa预处理+二分+最大匹配)
- loj 1201(最大独立集)
- Ligthoj 1154--Penguins【最大流 && 拆点】
- loj 1004(dp)
- poj 2378(树形dp)
- poj 1463(树形dp)
- loj 1011(状态压缩+记忆化搜索)
- loj 1013(LCS+记忆化搜索)
- loj 1154(最大流+枚举汇点)
- loj 1017(dp)
- loj 1018(状压dp+记忆化搜索)
- loj 1021(状压dp+记忆化搜索)
- loj 1025(记忆化搜索)
- loj 1155(最大流)
- loj 1156(二分+最大流)
- loj 1150(spfa预处理+二分+最大匹配)
- loj 1031(区间dp+记忆化搜索)