0
点赞
收藏
分享

微信扫一扫

POJ3498最大流,枚举终点,企鹅,基础最大流

624c95384278 2022-07-27 阅读 29

题意:
      有一n个冰块,每个冰块上都有一些企鹅,所有的企鹅要跳到一个冰块上去,但是由于起跳是的后坐力原因导致每个冰块最多条mi次,最后问你所有的企鹅都跳到一个冰块上去的那块冰块可以是哪一块,输出所有肯能的终点冰块。


思路:
      比较简单,我们可以枚举终点,首先把终点拿出来,剩下的点拆点,拆成两个,限流是最多的跳跃次数,然后起点连接每个拆了的点的左侧的点,终点就是当前枚举的点,然后最大流判断下就行了,提醒下,建图的时候注意,不要多虚拟出来一些没用的点,一开始我的第一感觉就是三重的,后来在敲的时候突然感觉两重就够了,也就是最多200个点就行,还有就是当前枚举的重点的冰块上的企鹅不用动,别的没什么,因为比较简单,我就不解释太多了,不清楚的自己画画建出来的图应该很容易懂。

#include<queue>

#include<stdio.h>

#include<string.h>



#define N_node 200 + 10

#define N_edge 100000

#define INF 1000000000



using namespace std;



typedef struct

{

int to ,cost ,next;

}STAR;



typedef struct

{

int x ,t;

}DEP;



typedef struct

{

double x ,y;

int p ,c;

}NODE;



NODE node[N_node];

STAR E[N_edge];

DEP xin ,tou;

int list[N_node] ,listt[N_node] ,tot;

int deep[N_node] ,Ans[N_node];

int canlink[110][110];



void add(int a ,int b ,int c)

{

E[++tot].to = b;

E[tot].cost = c;

E[tot].next = list[a];

list[a] = tot;



E[++tot].to = a;

E[tot].cost = 0;

E[tot].next = list[b];

list[b] = tot;

}



int minn(int x ,int y)

{

return x < y ? x : y;

}



bool BFS_DEEP(int s ,int t ,int n)

{

memset(deep ,255 ,sizeof(deep));

xin.x = s ,xin.t = 0;

queue<DEP>q;

q.push(xin);

deep[s] = 0;

while(!q.empty())

{

tou = q.front();

q.pop();

for(int k = list[tou.x] ;k ;k = E[k].next)

{

xin.x = E[k].to;

xin.t = tou.t + 1;

if(deep[xin.x] != -1 || !E[k].cost)

continue;

deep[xin.x] = xin.t;

q.push(xin);

}

}

for(int i = 0 ;i <= n ;i ++)

listt[i] = list[i];

return deep[t] != -1;

}



int DFS_Flow(int s ,int t ,int flow)

{

if(s == t) return flow;

int nowflow = 0;

for(int k = listt[s] ;k ;k = E[k].next)

{

listt[s] = k;

int c = E[k].cost;

int to = E[k].to;

if(!c || deep[to] != deep[s] + 1)

continue;

int tmp = DFS_Flow(to ,t ,minn(c ,flow - nowflow));

nowflow += tmp;

E[k].cost -= tmp;

E[k^1].cost += tmp;

if(nowflow == flow) break;

}

if(!nowflow) deep[s] = 0;

return nowflow;

}



int DINIC(int s ,int t ,int n)

{

int ans = 0;

while(BFS_DEEP(s ,t ,n))

{

ans += DFS_Flow(s ,t ,INF);

}

return ans;

}



double Get_Dis(NODE a ,NODE b)

{

double x = (a.x - b.x) * (a.x - b.x);

double y = (a.y - b.y) * (a.y - b.y);

return x + y;

}



int main ()

{

int t ,n ,i ,j ,sump;

double dis;

scanf("%d" ,&t);

while(t--)

{

scanf("%d %lf" ,&n ,&dis);

sump = 0;

for(i = 1 ;i <= n ;i ++)

{

scanf("%lf %lf %d %d" ,&node[i].x ,&node[i].y ,&node[i].p ,&node[i].c);

sump += node[i].p;

}

memset(canlink ,0 ,sizeof(canlink));

for(i = 1 ;i <= n ;i ++)

for(j = i + 1 ;j <= n ;j ++)

{

if(Get_Dis(node[i] ,node[j]) <= dis * dis)

canlink[i][j] = canlink[j][i] = 1;

}

int ansid = 0;

for(int now = 1 ;now <= n ;now ++)

{

memset(list ,0 ,sizeof(list));

tot = 1;

for(i = 1 ;i <= n ;i ++)

{

if(i == now) continue;

add(0 ,i ,node[i].p);

add(i ,i + n ,node[i].c);

}

for(i = 1 ;i <= n ;i ++)

for(j = i + 1 ;j <= n ;j ++)

{

if(canlink[i][j])

{

if(i == now) add(j + n ,now ,INF);

else if(j == now) add(i + n ,now ,INF);

else add(i + n ,j ,INF) ,add(j + n ,i ,INF);

}

}

int flow = DINIC(0 ,now ,n + n);

if(flow == sump - node[now].p)

Ans[++ansid] = now;

}

if(!ansid) printf("-1\n");

else

{

for(i = 1 ;i <= ansid ;i ++)

if(i == ansid) printf("%d\n" ,Ans[i] - 1);

else printf("%d " ,Ans[i] - 1);

}

}

return 0;

}













举报

相关推荐

0 条评论