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 }






posted on 2012-04-02 22:01  kevinkitty  阅读(841)  评论(0编辑  收藏  举报

导航