zoukankan      html  css  js  c++  java
  • 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.

    输入

    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.

    输出

    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
    ",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
    ",i-1,y-n-1);
    268                 }
    269             }
    270         }
    271     }
    272     return 0;
    273 }
    View Code
  • 相关阅读:
    东南亚互联网创业哪些领域比较有前景?
    2021最新最实用.NET Core笔试题附答案
    2021UpdateC#.NET笔试题基础篇
    Ubuntu下 安装MiniGUI
    MiniGUI 如何显示繁体字
    Android 基础一 TextView,Style样式,Activity 传值,选择CheckBox 显示密码
    【玩转开源】BananaPi R2 —— 第一篇 Openwrt安装
    JAVA面对对象(二)——继承、方法的覆写
    JAVA面对对象(一)——封装
    JAVA关键字及作用
  • 原文地址:https://www.cnblogs.com/lglh/p/9626346.html
Copyright © 2011-2022 走看看