日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

洛谷P3357:最长k可重线段集问题(网络流)

發布時間:2023/12/3 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 洛谷P3357:最长k可重线段集问题(网络流) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

解析

本題的建模方法有很多,我的做法是補集思想轉化成志愿者招募然后按照那道題的做法直接做,看題解更多是采用的對于不沖突的線段首尾加邊的做法。
在前一道最長k可重區間問題中這兩種做法談不上孰優孰劣,但本題中題解的做法在處理垂直線段時更加簡單。

做法和上一題似乎很像,區別一是權值定義有變,二就是關鍵的垂直線段處理了。
按照題解的做法,直接特判討論即可。
如果按照志愿者招募呢?
注意到,一條 x=cx=cx=c 的垂直線段和 (l,c),(c,r)(l,c),(c,r)(l,c),(c,r) 都是不沖突的。
考慮如何表示。
對于不垂直的線段 (l,r)(l,r)(l,r),將其改為 (2l+1,2r)(2l+1,2r)(2l+1,2r)
對于垂直線段 x=cx=cx=c 將其改為 (2c,2c+1)(2c,2c+1)(2c,2c+1)
這樣,在不破壞原來沖突性質的前提下,很好的實現我們的要求。

#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define debug(...) fprintf(stderr,__VA_ARGS__) #define ok debug("OK\n") inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; } const int N=3e5+100; const int M=1e6+100; const int inf=1e9;int n,m,k;int s,t,tot; struct node{int to,nxt,cap;int w; }p[N]; int fi[N],cnt,cur[N]; inline void addline(int x,int y,int c,int w){p[++cnt]=(node){y,fi[x],c,w};fi[x]=cnt;return; } inline void add(int x,int y,int c,int w){addline(x,y,c,w);addline(y,x,0,-w);return; }int dis[N]; int vis[N]; queue<int>q; bool spfa(){fill(dis,dis+1+tot,inf);dis[s]=0;q.push(s);vis[s]=1;while(!q.empty()){int now=q.front();q.pop();vis[now]=0;for(int i=cur[now]=fi[now];~i;i=p[i].nxt){int to=p[i].to;if(dis[to]<=dis[now]+p[i].w||!p[i].cap) continue;dis[to]=dis[now]+p[i].w;if(!vis[to]) vis[to]=1,q.push(to);}}return dis[t]<inf; } int cost; int flow; int dfs(int x,int lim){if(vis[x]) return 0;if(x==t||!lim){cost+=lim*dis[t];return lim;}vis[x]=1;int res(0);for(int &i=cur[x];~i;i=p[i].nxt){int to=p[i].to;if(dis[to]!=dis[x]+p[i].w) continue;int add=dfs(to,min(lim,p[i].cap));res+=add;lim-=add;p[i].cap-=add;p[i^1].cap+=add;if(!lim) break;}if(!res) dis[x]=-1;vis[x]=0;return res; } void dinic(){flow=cost=0;int tmp(0);while(spfa()){while((tmp=dfs(s,inf))) flow+=tmp;}return; } int que[1050],l[1050],r[1050],sum[1050],num; int val[1050],ans; signed main(){#ifndef ONLINE_JUDGE//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);#endifmemset(fi,-1,sizeof(fi));cnt=-1;n=read();k=read();for(int i=1;i<=n;i++){int a=read(),b=read(),c=read(),d=read();if(a>c){swap(a,c);swap(b,d);} val[i]=floor(sqrt(1ll*(a-c)*(a-c)+1ll*(b-d)*(b-d)));ans+=val[i];a<<=1;c<<=1;if(a==c) c++;else a++;l[i]=a;r[i]=c;que[++num]=l[i];que[++num]=r[i];}sort(que+1,que+1+num);num=unique(que+1,que+1+num)-que-1;tot=num;s=++tot;t=++tot;add(s,1,inf,0);add(num,t,inf,0);for(int i=1;i<=n;i++){l[i]=lower_bound(que+1,que+1+num,l[i])-que;r[i]=lower_bound(que+1,que+1+num,r[i])-que;sum[l[i]]++;sum[r[i]]--;//printf("(%d %d)\n",l[i],r[i]);add(l[i],r[i],1,val[i]);}for(int i=1;i<num;i++){sum[i]+=sum[i-1];int o=max(sum[i]-k,0);//printf("i=%d sum=%d o=%d\n",i,sum[i],o);add(i,i+1,inf-o,0);}dinic();ans-=cost;printf("%d\n",ans);return 0; } /* 4 2 2 0 7 4 5 4 8 6 0 5 8 6 3 1 4 6 */

總結

以上是生活随笔為你收集整理的洛谷P3357:最长k可重线段集问题(网络流)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。