1. 程式人生 > >BZOJ1486:[HNOI2009]最小圈——題解

BZOJ1486:[HNOI2009]最小圈——題解

namespace con user 這樣的 const 題解 main esp add

https://www.lydsy.com/JudgeOnline/problem.php?id=1486

https://www.luogu.org/problemnew/show/P3199

題面太鬼畜就不粘了。

這題唯一正確的解法是https://www.luogu.org/blog/user7868/solution-p3199雖然我看不懂。

當然為了AC這道題於是拋棄自己的靈魂寫了dfs-spfa結果跑的飛快。

這樣的題算是出鍋了吧……

簡單講下做法,二分答案,對每條邊減去這個答案搜負環,如果存在的話該答案合法,否則不合法。

#include<cmath>
#include
<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef double dl; const dl INF=1e7; const dl eps=1e-9; const int N=3e3+5; const int M=1e4+5; struct node{ int to,nxt; dl w; }e[M]; int cnt,head[N],n,m,sum[N];
bool vis[N],ok; dl dis[N]; queue<int>q; inline void add(int u,int v,dl w){ e[++cnt].to=v;e[cnt].w=w;e[cnt].nxt=head[u];head[u]=cnt; } void spfa(int u){ vis[u]=1; for(int i=head[u];i&&!ok;i=e[i].nxt){ int v=e[i].to;dl w=e[i].w; if(dis[v]>=dis[u]+w){ dis[v]
=dis[u]+w; if(vis[v]||ok){ok=1;return;} spfa(v); } } vis[u]=0; } bool pan(dl delta){ for(int i=1;i<=m;i++)e[i].w-=delta; for(int i=1;i<=n;i++)vis[i]=0,dis[i]=0; ok=0; for(int i=1;i<=n&&!ok;i++) spfa(i); for(int i=1;i<=m;i++)e[i].w+=delta; return ok; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v;dl w; scanf("%d%d%lf",&u,&v,&w); add(u,v,w); } dl l=-INF,r=INF; while(fabs(r-l)>eps){ dl mid=(l+r)/2; if(pan(mid))r=mid; else l=mid; } printf("%.8lf\n",l); return 0; }

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+歡迎訪問我的博客:http://www.cnblogs.com/luyouqi233/ +

+++++++++++++++++++++++++++++++++++++++++++

BZOJ1486:[HNOI2009]最小圈——題解