Hubtown(最大流)
Hubtown
时间限制: 1 Sec 内存限制: 128 MB提交: 23 解决: 11
[提交] [状态] [讨论版] [命题人:admin]
题目描述
Hubtown is a large Nordic city which is home to n citizens. Every morning, each of its citizens wants to travel to the central hub from which the city gets its name, by using one of the m commuter trains which pass through the city. Each train line is a ray (i.e., a line segment which extends infinitely long in one direction), ending at the central hub, which is located at coordinates (0, 0). However, the train lines have limited capacity (which may vary between train lines), so some train lines may become full, leading to citizens taking their cars instead of commuting. The city council wishes to minimize the number of people who go by car. In order to do this, they will issue instructions stating which citizens are allowed to take which train.
A citizen will always take the train line which is of least angular distance from its house. However, if a citizen is exactly in the middle between two train lines, they are willing to take either of them, and city council can decide which of the two train lines the citizen should use.
See Figure H.1 for an example.
Figure H.1: Illustration of Sample Input 1. The dashed arrows indicate which train lines the citizens are closest to (note that we are measuring angular distances, not Euclidean distance).
Your task is to help the council, by finding a maximum size subset of citizens who can go by train in the morning to the central hub, ensuring that each of the citizens take one of the lines they are closest to, while not exceeding the capacity of any train line. For this subset, you should also print what train they are to take.
A citizen will always take the train line which is of least angular distance from its house. However, if a citizen is exactly in the middle between two train lines, they are willing to take either of them, and city council can decide which of the two train lines the citizen should use.
See Figure H.1 for an example.
Figure H.1: Illustration of Sample Input 1. The dashed arrows indicate which train lines the citizens are closest to (note that we are measuring angular distances, not Euclidean distance).
Your task is to help the council, by finding a maximum size subset of citizens who can go by train in the morning to the central hub, ensuring that each of the citizens take one of the lines they are closest to, while not exceeding the capacity of any train line. For this subset, you should also print what train they are to take.
输入
The first line of input contains two integers n and m, where 0 ≤ n ≤ 200 000 is the number of citizens, and 1 ≤ m ≤ 200 000 is the number of train lines.
The next n lines each contain two integers x and y, the Cartesian coordinates of a citizen’s home. No citizen lives at the central hub of the city.
Then follow m lines, each containing three integers x, y, and c describing a train line, where (x, y) are the coordinates of a single point (distinct from the central hub of the city) which the train line passes through and 0 ≤ c ≤ n is the capacity of the train line. The train line is the ray starting at (0, 0) and passing through (x, y).
All coordinates x and y (both citizens’ homes and the points defining the train lines) are bounded by 1000 in absolute value. No two train lines overlap, but multiple citizens may live at the same coordinates.
The next n lines each contain two integers x and y, the Cartesian coordinates of a citizen’s home. No citizen lives at the central hub of the city.
Then follow m lines, each containing three integers x, y, and c describing a train line, where (x, y) are the coordinates of a single point (distinct from the central hub of the city) which the train line passes through and 0 ≤ c ≤ n is the capacity of the train line. The train line is the ray starting at (0, 0) and passing through (x, y).
All coordinates x and y (both citizens’ homes and the points defining the train lines) are bounded by 1000 in absolute value. No two train lines overlap, but multiple citizens may live at the same coordinates.
输出
First, output a single integer s – the maximum number of citizens who can go by train. Then,output s lines, one for each citizen that goes by train. On each line, output the index of the citizen followed by the index of the train line the citizen takes. The indices should be zero-indexed (i.e.,between 0 and n − 1 for citizens, and between 0 and m − 1 for train lines, respectively), using the same order as they were given in the input.
样例输入
3 2
2 0
-1 0
-2 -1
1 -1 1
1 1 2
样例输出
3
0 1
1 1
2 0
思路:极角排序,建边求最大流!
AC代码;
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef long double ld; 5 const ld epsss=1e-10; 6 const int N=4e5+10,M=2e6+10,inf=0x3f3f3f3f; 7 int n,m; 8 int ST,ED,ID; 9 int first[N],w[M],cap[M],nxt[M]; 10 void ins(int x,int y,int cap_) 11 { 12 w[++ID]=y; 13 cap[ID]=cap_; 14 nxt[ID]=first[x]; 15 first[x]=ID; 16 w[++ID]=x; 17 cap[ID]=0; 18 nxt[ID]=first[y]; 19 first[y]=ID; 20 } 21 int d[N]; 22 bool bfs() 23 { 24 memset(d,-1,sizeof(d)); 25 d[ST]=0; 26 queue<int>q; 27 q.push(ST); 28 while(!q.empty()) 29 { 30 int x=q.front(); 31 q.pop(); 32 for(int z=first[x];z;z=nxt[z]) 33 if(cap[z]) 34 { 35 int y=w[z]; 36 if(d[y]==-1) 37 { 38 d[y]=d[x]+1; 39 if(y==ED) return 1; 40 q.push(y); 41 } 42 } 43 } 44 return 0; 45 } 46 int dfs(int x,int all) 47 { 48 if(x==ED) return all; 49 int use=0; 50 for(int z=first[x];z;z=nxt[z]) 51 if(cap[z]) 52 { 53 int y=w[z]; 54 if(d[y]==d[x]+1) 55 { 56 int tmp=dfs(y,min(cap[z],all-use)); 57 cap[z]-=tmp; 58 cap[z^1]+=tmp; 59 use+=tmp; 60 if(use==all) break; 61 } 62 } 63 if(use==0) d[x]=-1; 64 return use; 65 } 66 int dinic() 67 { 68 int tmp=0; 69 while(bfs()) 70 tmp+=dfs(ST,inf); 71 return tmp; 72 } 73 struct A 74 { 75 int x,y,o; 76 } a[N]; 77 struct B 78 { 79 int x,y,o,c; 80 } b[N]; 81 struct E 82 { 83 int x,y,t; 84 int sgn; 85 E() {} 86 E(int _x,int _y,int _t) 87 { 88 x=_x,y=_y,t=_t; 89 if(!x) sgn=y>0; 90 else sgn=x>0; 91 } 92 } e[400010]; 93 bool cmpe(const E&a,const E&b) 94 { 95 if(a.sgn!=b.sgn) return a.sgn<b.sgn; 96 int t=a.x*b.y-a.y*b.x; 97 if(t) return t<0; 98 return a.t<b.t; 99 } 100 int pre[400010],suf[400010]; 101 int gcd(int a,int b) 102 { 103 return b?gcd(b,a%b):a; 104 } 105 bool point_on_line(const A&a,const B&b) 106 { 107 int d1=gcd(abs(a.x),abs(a.y)),d2=gcd(abs(b.x),abs(b.y)); 108 return (a.x/d1==b.x/d2)&&(a.y/d1==b.y/d2); 109 } 110 struct Point 111 { 112 ll x,y; 113 Point() {} 114 Point(ll _x,ll _y) 115 { 116 x=_x,y=_y; 117 } 118 }; 119 ll cross(const Point &a,const Point &b) 120 { 121 return a.x*b.y-a.y*b.x; 122 } 123 ll sig(ll x) 124 { 125 if(x==0) return 0; 126 return x>0?1:-1; 127 } 128 struct Pointd 129 { 130 ld x,y; 131 Pointd() {} 132 Pointd(ld _x,ld _y) 133 { 134 x=_x,y=_y; 135 } 136 }; 137 ld crossd(const Pointd&a,const Pointd&b) 138 { 139 return a.x*b.y-a.y*b.x; 140 } 141 ll sigd(ld x) 142 { 143 if(fabs(x)<epsss) return 0; 144 return x>0?1:-1; 145 } 146 int distance_cmp(const A&_a,const B&_b,const B&_c) 147 { 148 Point a(_a.x,_a.y); 149 Point b(_b.x,_b.y); 150 Point c(_c.x,_c.y); 151 Point d; 152 if(!cross(b,c)) 153 { 154 d=Point(-b.y,b.x); 155 if(!cross(a,d)) 156 return 0; 157 if(sig(cross(d,a))==sig(cross(d,b))) 158 return -1; 159 return 1; 160 } 161 ld L=sqrt(b.x*b.x+b.y*b.y); 162 ld R=sqrt(c.x*c.x+c.y*c.y); 163 Pointd aa(a.x,a.y); 164 Pointd bb(b.x,b.y); 165 Pointd cc(c.x,c.y); 166 bb.x*=R; 167 bb.y*=R; 168 cc.x*=L; 169 cc.y*=L; 170 Pointd dd=Pointd(bb.x+cc.x,bb.y+cc.y); 171 if(!sigd(crossd(aa,dd))) 172 return 0; 173 if(sigd(crossd(dd,aa))==sigd(crossd(dd,bb))) 174 return -1; 175 return 1; 176 } 177 int main() 178 { 179 while(~scanf("%d %d",&n,&m)) 180 { 181 ST=0; 182 ED=n+m+1; 183 ID=1; 184 memset(first,0,sizeof(first)); 185 for(int i=1;i<=n;++i) 186 { 187 scanf("%d %d",&a[i].x,&a[i].y); 188 a[i].o=i; 189 } 190 for(int i=1;i<=m;++i) 191 { 192 scanf("%d %d %d",&b[i].x,&b[i].y,&b[i].c); 193 b[i].o=i; 194 } 195 int ce=0; 196 for(int i=1; i<=n; i++) 197 { 198 e[++ce]=E(a[i].x,a[i].y,i); 199 } 200 for(int i=1; i<=m; i++) 201 { 202 e[++ce]=E(b[i].x,b[i].y,-i); 203 } 204 sort(e+1,e+ce+1,cmpe); 205 pre[0]=0; 206 for(int i=1; i<=ce; i++) 207 if(e[i].t<0) 208 pre[0]=-e[i].t; 209 for(int i=1; i<=ce; i++) 210 { 211 pre[i]=pre[i-1]; 212 if(e[i].t<0) 213 pre[i]=-e[i].t; 214 } 215 suf[ce+1]=0; 216 for(int i=ce; i; i--) 217 if(e[i].t<0) 218 suf[ce+1]=-e[i].t; 219 for(int i=ce; i; i--) 220 { 221 suf[i]=suf[i+1]; 222 if(e[i].t<0) 223 suf[i]=-e[i].t; 224 } 225 for(int i=1; i<=ce; i++) 226 if(e[i].t>0) 227 { 228 int x=e[i].t; 229 int L=pre[i],R=suf[i]; 230 if(L==R) 231 { 232 ins(x,L+n,1); 233 continue; 234 } 235 if(point_on_line(a[x],b[L])) 236 { 237 ins(x,L+n,1); 238 continue; 239 } 240 if(point_on_line(a[x],b[R])) 241 { 242 ins(x,R+n,1); 243 continue; 244 } 245 int t=distance_cmp(a[x],b[L],b[R]); 246 if(t<=0) 247 ins(x,L+n,1); 248 if(t>=0) 249 ins(x,R+n,1); 250 } 251 for(int i=1;i<=n;++i) 252 { 253 ins(ST,i,1); 254 } 255 for(int i=1;i<=m;++i) 256 { 257 ins(n+i,ED,b[i].c); 258 } 259 printf("%d\n",dinic()); 260 for(int i=1;i<=n;++i) 261 { 262 for(int z=first[i];z;z=nxt[z]) 263 { 264 int y=w[z]; 265 if(y>n && cap[z]==0) 266 { 267 printf("%d %d\n",i-1,y-n-1); 268 } 269 } 270 } 271 } 272 return 0; 273 }