zoukankan      html  css  js  c++  java
  • [hdu-6808] Go Running 最小点覆盖 网络流 2020多校4

    【题目链接】http://acm.hdu.edu.cn/showproblem.php?pid=6808

    【题目大意】

    坐标轴上,人可以选择自己开始跑步的时间、位置、方向(正方向/负方向)

    有n个观测点给出观测时间和坐标,此处此时至少有一个人跑步,问最少有几个人跑步


    转变为选最少的直线(斜率为1或-1)覆盖坐标中的点
    可以把坐标旋转45°,转变为画平行于x或y轴的直线覆盖所有点
    把点的x坐标和y坐标分别作为二分图中两侧的点,连边
    转变为二分图最小点覆盖的问题 。最小点覆盖=二分图最大匹配 

    ps:数据量太大,需要用dinic跑最大流

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 int const maxn=2e5+7,maxn2=1e5+7;;
      4 typedef long long ll;
      5 const ll inf=1e18;
      6 int s,t,n,id1[maxn],id2[maxn],fr[maxn2],to[maxn2],numid1,numid2,tot;
      7 int cur[maxn],head[maxn],deep[maxn];
      8 void init(){
      9     memset(id1,0,sizeof(id1));
     10     memset(id2,0,sizeof(id2));
     11     memset(head,-1,sizeof(head));
     12     numid1=0;
     13     numid2=0;
     14     tot=-1;
     15 }
     16 struct edge{
     17     int to,nxt;
     18     ll flow;
     19 }e[maxn*6];
     20 void build(int x,int y,int z){
     21     e[++tot].to=y;
     22     e[tot].flow=z;
     23     e[tot].nxt=head[x];
     24     head[x]=tot;
     25     // printf("%d : %d %d 
    ",tot,x,y,z);
     26 }
     27 //二分图反相边
     28 void build_dinci(int x,int y,int z){
     29     e[++tot].to=y;e[tot].flow=z;e[tot].nxt=head[x];head[x]=tot;
     30     e[++tot].to=x;e[tot].flow=0;e[tot].nxt=head[y];head[y]=tot;
     31 }
     32 queue<int>q;
     33 int bfs(){
     34     while(!q.empty())q.pop();
     35     memset(deep,0,sizeof(deep));
     36     deep[s]=1;
     37     q.push(s);
     38     while(!q.empty()){
     39         int u=q.front();q.pop();
     40         for(int i=head[u];i!=-1;i=e[i].nxt){
     41             if(e[i].flow&&!deep[e[i].to]){//要还有流量
     42                 deep[e[i].to]=deep[u]+1;
     43                 q.push(e[i].to);
     44             }
     45         }
     46     }
     47     return deep[t];
     48 }
     49 ll    dfs(int u,ll limit){
     50     if(u==t)return limit;
     51     for(int &i=cur[u];i!=-1;i=e[i].nxt){//当前弧优化  i是cur[i],下一个还没被访问过的边
     52        //int& 是引用,变量别名,修改i就修改了cur[u]
     53         int v=e[i].to;
     54         if(deep[v]==deep[u]+1&&e[i].flow){//u只能由deep[u]-1到达
     55             ll nowdi=dfs(v,min(limit,e[i].flow));
     56             if(nowdi){
     57                 e[i].flow-=nowdi;
     58                 e[i^1].flow+=nowdi;
     59                 return nowdi;
     60             }
     61         }
     62     }
     63     return 0;
     64 }
     65 ll  dinic(){
     66     ll  ans=0;
     67     while(bfs()){
     68         for(int i=1;i<=n;i++)//bfs分层
     69             cur[i]=head[i];
     70         ll d=dfs(s,inf);
     71         while(d){
     72             ans+=d;//寻找增广路
     73             d=dfs(s,inf);
     74         }
     75     }
     76     return ans;
     77 }
     78 int main(){
     79     int T,a,b;
     80     scanf("%d",&T);
     81     while(T--){
     82         scanf("%d",&n);
     83         init();
     84         for(int i=1;i<=n;i++){
     85             scanf("%d%d",&a,&b);
     86             fr[i]=b-a+1e5,to[i]=b+a;
     87             //把图旋转45°,转化成画平行于x或者y轴的线,y-x   y+x
     88             if(!id1[fr[i]])id1[fr[i]]=++numid1;
     89             if(!id2[to[i]])id2[to[i]]=++numid2;
     90         }
     91 /*planb
     92 先存下来,然后离散化(用时间换空间)
     93 (此处用空间换时间)
     94 
     95 题意概述:
     96 人可以选择自己开始跑步的位置和方向,问最少有几个人跑步
     97 转变为选最少的直线(斜率为1或-1)覆盖坐标中的点
     98 可以把坐标旋转45°,转变为画平行于x或y轴的直线覆盖所有点
     99 
    100 把点的x坐标和y坐标分别作为二分图中两侧的点,连边
    101 转变为二分图最小点覆盖的问题 。最小点覆盖=二分图最大匹配  ,数据量太大,需要用dinic跑最大流
    102 */
    103         s=numid1+numid2+1,t=s+1;
    104         for(int i=1;i<=n;i++){
    105             build_dinci(id1[fr[i]],id2[to[i]]+numid1,1);
    106         }
    107         //注意二分图两边的点,   只和源点/汇点 加一次!!
    108         for(int i=1;i<=numid1;i++){
    109             build_dinci(s,i,1);
    110         }
    111         for(int i=1;i<=numid2;i++){
    112             build_dinci(i+numid1,t,1);
    113         }
    114         n=numid1+numid2+2;
    115         ll ans=dinic();
    116         printf("%lld
    ",ans);
    117         
    118     }
    119     return 0;
    120 }
  • 相关阅读:
    Atlas
    MHA高可用
    Mycat 读写分离
    数据库 基于GTID主从复制
    DHCP服务
    python垃圾回收机制
    深拷贝、浅拷贝、引用(总结)
    python内存管理机制
    web安全-横向越权与纵向越权
    登录功能SQL注入
  • 原文地址:https://www.cnblogs.com/conver/p/13796795.html
Copyright © 2011-2022 走看看