• poj 3498


    March of the Penguins
    Time Limit: 8000MS   Memory Limit: 65536K
    Total Submissions: 3345   Accepted: 1532

    Description

    Somewhere near the south pole, a number of penguins are standing on a number of ice floes. Being social animals, the penguins would like to get together, all on the same floe. The penguins do not want to get wet, so they have use their limited jump distance to get together by jumping from piece to piece. However, temperatures have been high lately, and the floes are showing cracks, and they get damaged further by the force needed to jump to another floe. Fortunately the penguins are real experts on cracking ice floes, and know exactly how many times a penguin can jump off each floe before it disintegrates and disappears. Landing on an ice floe does not damage it. You have to help the penguins find all floes where they can meet.

    A sample layout of ice floes with 3 penguins on them.

    Input

    On the first line one positive number: the number of testcases, at most 100. After that per testcase:

    • One line with the integer N (1 ≤ N ≤ 100) and a floating-point number D (0 ≤ D ≤ 100 000), denoting the number of ice pieces and the maximum distance a penguin can jump.

    • N lines, each line containing xiyini and mi, denoting for each ice piece its X and Y coordinate, the number of penguins on it and the maximum number of times a penguin can jump off this piece before it disappears (−10 000 ≤ xiyi ≤ 10 000, 0 ≤ ni ≤ 10, 1 ≤ mi ≤ 200).

    Output

    Per testcase:

    • One line containing a space-separated list of 0-based indices of the pieces on which all penguins can meet. If no such piece exists, output a line with the single number −1.

    Sample Input

    2
    5 3.5
    1 1 1 1
    2 3 0 1
    3 5 1 1
    5 1 1 1
    5 4 0 1
    3 1.1
    -1 0 5 10
    0 0 3 9
    2 0 1 1

    Sample Output

    1 2 4
    -1
    题意描述:
    二维平面上有n个浮冰(用坐标表示浮冰位置),开始时每个浮冰上有一些企鹅,现在企鹅需要聚到某一个浮冰上,因此需要从一个浮冰跳到另一个浮冰上。浮冰比较特殊,每次企鹅跳离该浮冰时,由于反弹作用,浮冰会消融一部分,现在告诉,每块浮冰的坐标(xi,yi),每块浮冰最多可以被企鹅跳的次数(ni),每块浮冰上初始的企鹅数量(mi)以及企鹅可以跳跃的最大距离D。求这些企鹅最后可以在哪些浮冰上汇聚。输出可以汇聚的浮冰序号,下标从0..n-1,如果不能汇聚,输出-1。
    思路:网络流解法,将浮冰拆点,i,i'。
    1、从源点S到有企鹅的浮冰建立一条边 S->i = 浮冰上的企鹅数。
    2、从i->i'建边,边权为浮冰i可以跳出的次数。
    3、如果企鹅可以从浮冰i跳到j,则建边 i'->j = j'->i = INF
    最后枚举i作为汇点,看流量是不是总企鹅数。
    经验:
    SAP比DINIC快!
    SAP代码:375MS
    View Code
      1 #include<iostream>
    2 #include<algorithm>
    3 #include<cstring>
    4 #include<cmath>
    5
    6 using namespace std;
    7 #define INF 2000000000
    8 #define min2(a,b) (a<b)?a:b
    9 #define M 40005
    10 #define N 215
    11 struct EDGE{
    12 int v,re,next,w;
    13 }edge[M];
    14 int f[M];
    15 int head[N],totaledge,totalpoint;
    16 int cnt[N],d[N];
    17 void clear_graph()
    18 {
    19 totaledge=0;
    20 memset(head,-1,sizeof(head));
    21 }
    22 void out_graph(int n)
    23 {
    24 for(int u=0;u<n;u++)
    25 {
    26 cout<<"for u="<<u<<":";
    27 for(int e=head[u];e!=-1;e=edge[e].next)
    28 cout<<""<<edge[e].v<<","<<edge[e].w;
    29 cout<<endl;
    30 }
    31 }
    32 void add_edge(int u,int v,int w)
    33 {
    34 edge[++totaledge].v=v;edge[totaledge].w=w;
    35 edge[totaledge].next=head[u];head[u]=totaledge;
    36 edge[totaledge].re=totaledge+1;
    37
    38 edge[++totaledge].v=u;edge[totaledge].w=0;
    39 edge[totaledge].next=head[v];head[v]=totaledge;
    40 edge[totaledge].re=totaledge-1;
    41 }
    42 int dfs(int S,int T,int u,int UP)
    43 {
    44 if(u==T)return UP;
    45 int temp=UP,pos=totalpoint-1;
    46 for(int e=head[u];e!=-1;e=edge[e].next)
    47 {
    48 if(d[u]==d[edge[e].v]+1 && edge[e].w>f[e])
    49 {
    50 int canflow=dfs(S,T,edge[e].v,min2(UP,edge[e].w-f[e]));
    51 UP-=canflow;
    52 f[e]+=canflow;
    53 f[edge[e].re]-=canflow;
    54 if(!UP || d[S]==totalpoint)return temp-UP;
    55 }
    56 if(edge[e].w>f[e] && pos>d[edge[e].v])pos=d[edge[e].v];
    57 }
    58
    59 if(UP==temp)
    60 {
    61 cnt[d[u]]--;
    62 if(cnt[d[u]]==0)d[S]=totalpoint;
    63 else d[u]=pos+1,cnt[d[u]]++;
    64 }
    65 return temp-UP;
    66 }
    67 int SAP(int S,int T)
    68 {
    69 memset(d,0,sizeof(d));
    70 memset(cnt,0,sizeof(cnt));
    71 int ans=0;
    72 while(d[S]<totalpoint)
    73 ans+=dfs(S,T,S,INF);
    74 return ans;
    75 }
    76 double p[N][2],r;
    77 double dis(int i,int j)
    78 {
    79 return (p[i][0]-p[j][0])*(p[i][0]-p[j][0])
    80 + (p[i][1]-p[j][1])*(p[i][1]-p[j][1]);
    81 }
    82 int main()
    83 {
    84 int a,b,n,T,count,stack[N];
    85 cin>>T;
    86 while(T--)
    87 {
    88 cin>>n>>r;
    89 clear_graph();
    90 count=0;
    91 for(int i=1;i<=n;i++)
    92 {
    93 cin>>p[i][0]>>p[i][1]>>a>>b;
    94 add_edge(0,i,a);
    95 add_edge(i,i+n,b);
    96 count+=a;
    97 }
    98 for(int i=1;i<=n;i++)
    99 for(int j=i+1;j<=n;j++)
    100 if(dis(i,j)<=r*r)
    101 {
    102 add_edge(i+n,j,INF);
    103 add_edge(j+n,i,INF);
    104 }
    105
    106 totalpoint=2*n+2;
    107 stack[0]=0;
    108 for(int sink=1;sink<=n;sink++)
    109 {
    110 memset(f,0,sizeof(f));
    111 if(SAP(0,sink) == count)
    112 stack[++stack[0]]=sink-1;
    113 }
    114 if(stack[0])
    115 {
    116 cout<<stack[1];
    117 for(int i=2;i<=stack[0];i++)
    118 cout<<" "<<stack[i];
    119 cout<<endl;
    120 }
    121 else cout<<"-1"<<endl;
    122 }
    123
    124 return 0;
    125 }
    
    
    DINIC代码:1032MS
    
    
    View Code
      1 #include<iostream>
    2 #include<algorithm>
    3 #include<cstring>
    4 #include<cmath>
    5
    6 using namespace std;
    7 #define INF 2000000000
    8 #define min2(a,b) (a<b)?a:b
    9 #define M 40005
    10 #define N 215
    11 struct EDGE{
    12 int v,re,next,w;
    13 }edge[M];
    14 int f[M];
    15 int head[N],totaledge,totalpoint;
    16 int q[N],d[N];
    17 void clear_graph()
    18 {
    19 totaledge=0;
    20 memset(head,-1,sizeof(head));
    21 }
    22 void out_graph(int n)
    23 {
    24 for(int u=0;u<n;u++)
    25 {
    26 cout<<"for u="<<u<<":";
    27 for(int e=head[u];e!=-1;e=edge[e].next)
    28 cout<<""<<edge[e].v<<","<<edge[e].w;
    29 cout<<endl;
    30 }
    31 }
    32 void add_edge(int u,int v,int w)
    33 {
    34 edge[++totaledge].v=v;
    35 edge[totaledge].w=w;
    36 edge[totaledge].next=head[u];
    37 head[u]=totaledge;
    38 edge[totaledge].re=totaledge+1;
    39
    40 edge[++totaledge].v=u;
    41 edge[totaledge].w=0;
    42 edge[totaledge].next=head[v];
    43 head[v]=totaledge;
    44 edge[totaledge].re=totaledge-1;
    45 }
    46 bool bfs(int S,int T)
    47 {
    48 int u,e,front,rear;
    49 memset(d,-1,sizeof(d));
    50 front=rear=0;
    51 q[rear++]=S;
    52 d[S]=0;
    53 while(front!=rear)
    54 {
    55 u=q[front++];front^=(front==N)?N:0;
    56 for(e=head[u];e!=-1;e=edge[e].next)
    57 if(edge[e].w>f[e] && d[edge[e].v]==-1)
    58 {
    59 d[edge[e].v]=d[u]+1;
    60 q[rear++]=edge[e].v;
    61 rear^=(rear==N)?N:0;
    62 }
    63 }
    64 if(d[T]>=0)return true;
    65 else return false;
    66 }
    67 int dinic(int S,int T,int sum)
    68 {
    69 if(S==T)return sum;
    70 int tp=sum;
    71 for(int e=head[S];e!=-1 && sum;e=edge[e].next)
    72 if(d[edge[e].v]==d[S]+1 && edge[e].w>f[e])
    73 {
    74 int canflow=dinic(edge[e].v,T,min2(sum,edge[e].w-f[e]));
    75 f[e]+=canflow;
    76 f[edge[e].re]-=canflow;
    77 sum-=canflow;
    78 }
    79 return tp-sum;
    80 }
    81
    82 double p[N][2],r;
    83 double dis(int i,int j)
    84 {
    85 return (p[i][0]-p[j][0])*(p[i][0]-p[j][0])
    86 + (p[i][1]-p[j][1])*(p[i][1]-p[j][1]);
    87 }
    88 int main()
    89 {
    90 int a,b,n,T,cnt,stack[N];
    91 cin>>T;
    92 while(T--)
    93 {
    94 cin>>n>>r;
    95 clear_graph();
    96 cnt=0;
    97 for(int i=1;i<=n;i++)
    98 {
    99 cin>>p[i][0]>>p[i][1]>>a>>b;
    100 if(a) add_edge(0,i,a);
    101 add_edge(i,i+n,b);
    102 cnt+=a;
    103 }
    104 for(int i=1;i<=n;i++)
    105 for(int j=i+1;j<=n;j++)
    106 if(dis(i,j)<=r*r)
    107 {
    108 add_edge(i+n,j,INF);
    109 add_edge(j+n,i,INF);
    110 }
    111
    112 stack[0]=0;
    113 for(int sink=1;sink<=n;sink++)
    114 {
    115 memset(f,0,sizeof(f));
    116 int ans=0;
    117 while(bfs(0,sink))
    118 ans+=dinic(0,sink,INF);
    119 if(ans==cnt)stack[++stack[0]]=sink-1;
    120 }
    121 if(stack[0])
    122 {
    123 cout<<stack[1];
    124 for(int i=2;i<=stack[0];i++)
    125 cout<<" "<<stack[i];
    126 cout<<endl;
    127 }
    128 else cout<<"-1"<<endl;
    129 }
    130
    131 return 0;
    132 }



    
    
    
    
    
    
  • 相关阅读:
    js append()和appendChild()和insertBefore()的区别
    webpack打包工具简单案例
    Vue $ref 的用法
    Vue学习笔记-作用域插槽
    Vue学习笔记-插槽基本使用
    Vue学习笔记-父子通信案例
    Echarts案例-折线图
    Echarts案例-柱状图
    软件构造实验三-递归下降分析分析法
    软件构造实验二-拷贝一个c文件 将其中的关键字int替换成float
  • 原文地址:https://www.cnblogs.com/kevinkitty/p/kevinkitty_poj3498.html
Copyright © 2020-2023  润新知