2285: [Sdoi2011]保密【spfa】【最小权覆盖】
2016-03-07 15:37
337 查看
**
**
**
**
5 5
5 1 10 1
5 1 10 1
5 2 9 1
5 3 7 1
5 4 8 1
4 4
1 2
1 4
3 2
3 4
**
17.0
**
对30%的数据,n<=30
对60%的数据,n<=300
另外 40%的数据n1<=20
**
Stage2 day2
**
真是悲伤的一天QAQ
调了好久好久QAQ 早上刚刚和ls吐槽了自己的debug能力QAQ
这个flag立的真是太好了QAQ
瞬间就灵验了QAQ
首先看错题了
这里的危险度是每个小队的危险度之和
TAT刚开始以为是所有小队的距离和/安全值
想想也是简直了
然后有一个很神奇的优化……一定是我太213了QAQ
竟然忘了加QAQ
会在代码里标明就好
1.首先是一张二分图
2.【他们说叫分数规划 我不知道叫什么】求出来到每个点的ans
怎么求捏~?
我们先假设已经求出了 ans ans
如果存在更优解解那么一定满足
(t1+t2+t3+t4+⋅⋅⋅⋅+tn)/(s1+s2+s3+s4⋅⋅⋅⋅+sn)<=ans...(t1+t2+t3+t4+····+tn)/(s1+s2+s3+s4····+sn)<=ans ...
化简一下【左面的分母乘到右面然后再移项】
(t1−ans∗s1)+(t2−ans∗s2)+(t3−ans∗s3)+⋅⋅⋅(tn−ans∗sn)<0(t1-ans*s1)+(t2-ans*s2)+(t3-ans*s3)+ ···(tn-ans*sn)<0
所以我们二分ans就可以求出来 然后再跑最小权覆盖【貌似叫这个的样子】
**
——看不到光又怎样
Description
**现在,保密成为一个很重要也很困难的问题。如果没有做好,后果是严重的。比如,有个人没有自己去修电脑,又没有拆硬盘,后来的事大家都知道了。 当然,对保密最需求的当然是军方,其次才是像那个人。为了应付现在天上飞来飞去的卫星,军事基地一般都会建造在地下。 某K国的军事基地是这样子的:地面上两排大天井共n1个作为出入口,内部是许多除可以共享出入口外互不连通的空腔,每个空腔有且只有两个出入口,并且这两个出入口不会在同一排。为了方便起见,两排出入口分别编号为1,3,5…和2,4,6…并且最大的编号为n1。 虽然上面扯了那么多关于保密的东西,但是其实解密也是一件很纠结的事情。但其实最简单直接暴力无脑的解密方法就是找个人去看看。。。 我们有很牛X的特种部队,只需要派出一支特种部队到K国基地的某个出入口,那么和这个出入口直接相连的所有空腔都可以被探索,但也只有这些空腔可以被这支部队探索。现在有足够多的特种部队可以供你调遣,你必须使用他们调查完所有的K国基地内的空腔。 当然,你的基地离K国基地不会太近,周边的地图将会给你,表示为n个检查点和m条连接这些点的道路,其中点1到点n1就是K国基地的出入口,点n是你的部队的出发点。对每条道路,有不同的通行时间t和安全系数s。因为情报部门只对单向的道路安全系数进行了评估,所以这些道路只允许单向通行,并且不会存在环。 一支特种部队从你的基地出发,通过某条路径,到达某个K国基地出入口,此时这支部队的危险性表示为总时间和这条路径经过的所有道路的安全系数和的比值。整个行动的危险性表示为你派出的所有部队的危险性之和。你需要使这个值最小的情况下探索整个K国基地。 快点完成这个任务,在K国的叫兽宣布你是K国人之前。
**
Input
**第一行2个正整数n,m (4 <= n <= 700, m <= 100000) 表示整个地区地图上的检查点和道路数。 下面m行,每行4个正整数a, b, t, s(a, b <=n, 1 <= t, s <= 10)表示一条从a到b的道路需时为t,安全系数为s。 接下来1行2个正整数m1和n1(m1 <= 40000, n1 < min{n, 161}), m1表示K国基地空腔的个数,n1表示K国基地出入口的个数。 再接下来m1行,每行2个正整数u, v (u, v<=n1, u是奇数,v是偶数),表示每个空腔的2个出入口。
**
Output
**一行,最小的危险性,保留一位小数。或者输出”-1”(无引号)表示此任务不可能完成。
**
Sample Input
**5 5
5 1 10 1
5 1 10 1
5 2 9 1
5 3 7 1
5 4 8 1
4 4
1 2
1 4
3 2
3 4
**
Sample Output
**17.0
**
HINT
**对30%的数据,n<=30
对60%的数据,n<=300
另外 40%的数据n1<=20
**
Source
**Stage2 day2
**
Solution
**真是悲伤的一天QAQ
调了好久好久QAQ 早上刚刚和ls吐槽了自己的debug能力QAQ
这个flag立的真是太好了QAQ
瞬间就灵验了QAQ
首先看错题了
这里的危险度是每个小队的危险度之和
TAT刚开始以为是所有小队的距离和/安全值
想想也是简直了
然后有一个很神奇的优化……一定是我太213了QAQ
竟然忘了加QAQ
会在代码里标明就好
1.首先是一张二分图
2.【他们说叫分数规划 我不知道叫什么】求出来到每个点的ans
怎么求捏~?
我们先假设已经求出了 ans ans
如果存在更优解解那么一定满足
(t1+t2+t3+t4+⋅⋅⋅⋅+tn)/(s1+s2+s3+s4⋅⋅⋅⋅+sn)<=ans...(t1+t2+t3+t4+····+tn)/(s1+s2+s3+s4····+sn)<=ans ...
化简一下【左面的分母乘到右面然后再移项】
(t1−ans∗s1)+(t2−ans∗s2)+(t3−ans∗s3)+⋅⋅⋅(tn−ans∗sn)<0(t1-ans*s1)+(t2-ans*s2)+(t3-ans*s3)+ ···(tn-ans*sn)<0
所以我们二分ans就可以求出来 然后再跑最小权覆盖【貌似叫这个的样子】
**
Code
**#include <bits/stdc++.h> using namespace std; const int maxn=810; const double inf=1e12,eps=1e-8; struct edge{int to,next,w,s;}ed[100000+10]; int head[maxn],q[30000],h[maxn]; int n,m,n1,m1,las,fir,cnt,S,T; void ins1(int u,int v,int w,int s){cnt++;ed[cnt].to=v;ed[cnt].next=head[u];head[u]=cnt;ed[cnt].w=w;ed[cnt].s=s;} double dis[maxn],a[maxn],ans; bool inq[maxn]; bool spfa(int to,double res) { for(int i=1;i<=n;i++)dis[i]=inf,inq[i]=0; dis =las=fir=0; q[las++]=n;inq =1; while(fir<las) { int x=q[fir++]; for(int i=head[x];i;i=ed[i].next) if(dis[ed[i].to]>dis[x]+ed[i].w-res*ed[i].s) { dis[ed[i].to]=dis[x]+ed[i].w-res*ed[i].s; if(ed[i].to==to&&dis[ed[i].to]<0)return 1; if(!inq[ed[i].to]) { q[las++]=ed[i].to; inq[ed[i].to]=1; } } inq[x]=0; } return dis[to]<0; } struct data{int to,next;double w;}e[40000*4]; void ins(int u,int v,double w){cnt++;e[cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].w=w;} void insert(int u,int v,double w){ins(u,v,w);ins(v,u,0);} bool bfs() { for(int i=1;i<=T;i++)h[i]=-1; h[S]=las=fir=0; q[las++]=S; while(fir<las) { int x=q[fir++]; for(int i=head[x];i;i=e[i].next) if(e[i].w>0&&h[e[i].to]==-1) h[e[i].to]=h[x]+1,q[las++]=e[i].to; } return h[T]!=-1; } double dfs(int x,double f) { if(x==T)return f; double w,used=0; for(int i=head[x];i;i=e[i].next) if(e[i].w>0&&h[e[i].to]==h[x]+1) { w=dfs(e[i].to,min(e[i].w,f-used)); e[i].w-=w;e[i^1].w+=w; used+=w;if(fabs(f-used)<eps)return f; } if(fabs(used)<eps)h[x]=-1; return used; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int u,v,w,s; scanf("%d%d%d%d",&u,&v,&w,&s); ins1(u,v,w,s); } scanf("%d%d",&m1,&n1); for(int i=1;i<=n1;i++) { double l=0,r=10;int cou=20; while(cou--) { double mid=(l+r)*0.5; if(spfa(i,mid))r=mid; else l=mid; } if(dis[i]==inf)a[i]=inf; else a[i]=l; } memset(head,0,sizeof(head));cnt=1;S=n1+1;T=S+1; for(int i=1;i<=n1;i++) if(i&1)insert(S,i,a[i]); else insert(i,T,a[i]); for(int i=1;i<=m1;i++) { int u,v; scanf("%d%d",&u,&v); if(a[u]==inf&&a[v]==inf) { printf("-1"); return 0; } else insert(u,v,inf); } while(bfs()) ans+=dfs(S,inf); printf("%.1lf",ans); return 0; }
——看不到光又怎样
相关文章推荐
- 51nod1344 走格子
- Axure RP 7.0 注册码
- 二叉树
- 正则表达式问题
- PAT (Basic Level)1049. 数列的片段和
- 【转】Android系统中的.apk文件和dex文件
- 学习进度总结
- Redis Sentinel高可用架构
- 面向对象之里氏替换原则
- const用法
- LeetCode 8 String to Integer (atoi)
- 12306验证码破解思路分享
- 文章标题
- 博弈sg函数
- 阿里巴巴发布《2015移动安全漏洞年报》
- 快速排序(解析及代码实现)
- Android APP长期运行于后台,重启后如何避免异常
- Google Protocol Buffer 的使用和原理
- iOS mask 层 UIBezierPath path 放大
- vim命令图解