生活随笔
收集整理的這篇文章主要介紹了
洛谷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#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
]]--;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);add(i
,i
+1,inf
-o
,0);}dinic();ans
-=cost
;printf("%d\n",ans
);return 0;
}
總結
以上是生活随笔為你收集整理的洛谷P3357:最长k可重线段集问题(网络流)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。