zoukankan      html  css  js  c++  java
  • 洛谷P3357 最长k可重线段集问题(费用流)

    传送门

    其实和最长k可重区间集问题差不多诶……

    把这条开线段给压成x轴上的一条线段,然后按上面说的那种方法做即可

    然而有一个坑点是线段可以垂直于x轴,然后一压变成一个点,连上正权环,求最长路……然后spfa他就死了……

    怎么解决呢……把每一个区间的左右端点坐标扩大两倍,如果相等就$--l[i]$,否则$++l[i]$,这样的话能保证本来不能覆盖的点仍不能覆盖,本来可以覆盖的点仍可以覆盖

    似乎讲不清楚……感性理解一下好了……

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<queue>
     5 #include<cstring>
     6 #include<cmath>
     7 #include<algorithm>
     8 #define inf 0x3f3f3f3f
     9 #define ll long long
    10 using namespace std;
    11 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    12 char buf[1<<21],*p1=buf,*p2=buf;
    13 inline int read(){
    14     #define num ch-'0'
    15     char ch;bool flag=0;int res;
    16     while(!isdigit(ch=getc()))
    17     (ch=='-')&&(flag=true);
    18     for(res=num;isdigit(ch=getc());res=res*10+num);
    19     (flag)&&(res=-res);
    20     #undef num
    21     return res;
    22 }
    23 const int N=1005,M=4005;
    24 int ver[M],Next[M],head[N],edge[M],flow[M],tot=1;
    25 int dis[N],disf[N],vis[N],Pre[N],last[N],n,s,t,k;
    26 inline ll sqr(int x){return 1ll*x*x;}
    27 inline void add(int u,int v,int f,int e){
    28     ver[++tot]=v,Next[tot]=head[u],head[u]=tot,flow[tot]=f,edge[tot]=e;
    29     ver[++tot]=u,Next[tot]=head[v],head[v]=tot,flow[tot]=0,edge[tot]=-e;
    30 }
    31 queue<int> q;
    32 bool spfa(){
    33     memset(dis,0xef,sizeof(dis));
    34     q.push(s),dis[s]=0,disf[s]=inf,Pre[t]=-1;
    35     while(!q.empty()){
    36         int u=q.front();q.pop();vis[u]=0;
    37         for(int i=head[u];i;i=Next[i]){
    38             int v=ver[i];
    39             if(flow[i]&&dis[v]<dis[u]+edge[i]){
    40                 dis[v]=dis[u]+edge[i],Pre[v]=u,last[v]=i;
    41                 disf[v]=min(disf[u],flow[i]);
    42                 if(!vis[v]) vis[v]=1,q.push(v);
    43             }
    44         }
    45     }
    46     return ~Pre[t];
    47 }
    48 ll dinic(){
    49     int maxflow=0;ll maxcost=0;
    50     while(spfa()){
    51         int u=t;
    52         maxflow+=disf[t],maxcost+=1ll*disf[t]*dis[t];
    53         while(u!=s){
    54             flow[last[u]]-=disf[t];
    55             flow[last[u]^1]+=disf[t];
    56             u=Pre[u];
    57         }
    58     }
    59     return maxcost;
    60 }
    61 int l[N],r[N],x[N],y[N],st[N],val[N],m=0;
    62 int main(){
    63     n=read(),k=read();
    64     for(int i=1;i<=n;++i){
    65         l[i]=read(),x[i]=read(),r[i]=read(),y[i]=read();
    66         val[i]=sqrt(sqr(y[i]-x[i])+sqr(r[i]-l[i]));
    67         l[i]*=2,r[i]*=2;
    68         l[i]==r[i]?(--l[i]):(++l[i]);
    69         st[++m]=l[i],st[++m]=r[i];
    70     }
    71     sort(st+1,st+1+m);
    72     m=unique(st+1,st+1+m)-st-1;
    73     s=0,t=m+1;
    74     for(int i=s;i<t;++i) add(i,i+1,k,0);
    75     for(int i=1;i<=n;++i){
    76         l[i]=lower_bound(st+1,st+1+m,l[i])-st;
    77         r[i]=lower_bound(st+1,st+1+m,r[i])-st;
    78         add(l[i],r[i],1,val[i]);
    79     }
    80     printf("%lld
    ",dinic());
    81     return 0;
    82 }
  • 相关阅读:
    java并发容器
    实现个简单的线程池
    【hdu 3501 (数论、欧拉函数)】
    【关于Java学习的几点看法】
    【乘法游戏】
    【hdu 1280 前m大的数】
    【最大因子数】
    【ECJTU_ACM 11级队员2012年暑假训练赛(7) C Fire Net】
    【ACM ICPC Fighting!!!!!!!!!!!!!】
    【firefly 默默最喜欢的歌】
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9504034.html
Copyright © 2011-2022 走看看