首页 > 代码库 > SDOI 保密

SDOI 保密

P1339 - [SDOI2011]保密

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

 

二分图最小点权覆盖,求点权用二分答案,化简(s1+s2+……sn)/(t1+t2+……tn) <=ans  ,s1-t1*ans+s2-t2*ans……<0 ,spfa判断,。注意细节

  1 #include<algorithm>
  2 #include<iostream>
  3 #include<iomanip>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<cstdio>
  7 #include<queue>
  8 #include<ctime>
  9 #include<cmath>
 10 #include<stack>
 11 #include<map>
 12 #include<set>
 13 #define rep(i,a,b) for(register int i=a;i<=b;i++)
 14 #define il inline
 15 #define ll long long
 16 #define db double
 17 using namespace std;
 18 const int N=710,M=100010;
 19 const db inf=1e16;
 20 int n,m,n1,m1;
 21 struct E{
 22     int to,net;
 23     db t,s;
 24 }e[M];
 25 int head[N],num_e;
 26 db dis[N];
 27 int gi();
 28 void add(int x,int y,db t,db s) {
 29     e[++num_e].to=y , e[num_e].net=head[x] , head[x]=num_e , e[num_e].t=t , e[num_e].s=s;
 30 }
 31 bool inq[N];
 32 bool spfa(int t,double ans)  {
 33     rep(i,1,n) dis[i]=inf;
 34     memset(inq,0,sizeof(inq));
 35     queue<int> q;
 36     q.push(n);dis[n]=0;
 37     inq[n]=1;
 38     while(!q.empty()) {
 39     int u=q.front();q.pop();
 40     inq[u]=0;
 41     for(int i=head[u];i;i=e[i].net) {
 42         int to=e[i].to;
 43         if(dis[to]>dis[u]+e[i].t-e[i].s*ans) {
 44         dis[to]=dis[u]+e[i].t-e[i].s*ans;
 45         if(dis[t]<0) return true;
 46         if(!inq[to]) inq[to]=1,q.push(to);
 47         }
 48     }
 49     }
 50     return dis[t]<0;//  bug1 :dis[t]!=inf
 51 }
 52 struct data{
 53     int to,net;db flow,cap;
 54 }ed[M];
 55 int S,T,h[N];
 56 void insert(int x,int y,db c) {
 57     ed[++num_e].to=y;ed[num_e].net=head[x];head[x]=num_e;ed[num_e].cap=c;
 58 }
 59 bool bfs() {
 60     rep(i,1,T) h[i]=-1;// bug 4:rep(i,1,n1)
 61     queue<int> q;
 62     h[S]=0;
 63     q.push(S);// bug 5:h[n]=0;
 64     while(!q.empty()) {
 65     int u=q.front();q.pop();
 66     for(int i=head[u];i!=-1;i=ed[i].net) {//bug 3:i;
 67         int to=ed[i].to;
 68         if(h[to]==-1&&ed[i].cap>ed[i].flow) h[to]=h[u]+1,q.push(to);// bug 6 :  , q.push(to)
 69         if(h[T]!=-1) return true;
 70     }
 71     }
 72     return h[T]!=-1;
 73 }
 74 double dfs(int x,db f) {
 75     if(x==T) return f;
 76     db tag=0;
 77     for(int i=head[x];i!=-1;i=ed[i].net) {// bug2 : i;
 78     int to=ed[i].to;
 79     if(ed[i].cap>ed[i].flow&&h[to]==h[x]+1) {
 80         db flow=dfs(to,min(ed[i].cap-ed[i].flow,f-tag));
 81         ed[i].flow += flow;
 82         ed[i^1].flow -=flow;
 83         tag+=flow;
 84         if(fabs(f-tag)<0.00001) return tag;
 85     }
 86     }
 87     return tag;
 88 }
 89 db a[N];
 90 int main() {
 91     freopen("tfnhnsm.in","r",stdin);
 92     freopen("tfnhnsm.out","w",stdout);
 93     n=gi(),m=gi();
 94     rep(i,1,m) {
 95     int x=gi(),y=gi();db t,s;
 96     scanf("%lf%lf",&t,&s);
 97         add(x,y,t,s);
 98     }
 99         m1=gi(),n1=gi();
100     rep(i,1,n1) {//  n 
101       db l=0,r=10,cnt=20;
102      while(cnt--) {
103        db mid=(l+r)*0.5;
104        if(spfa(i,mid)) r=mid;
105        else l=mid;
106      }
107      if(dis[i]==inf) a[i]=inf;
108      else a[i]=l;
109    }
110 
111     memset(head,-1,sizeof(head)),num_e=-1;// bug4: head 0
112     S=n1+1,T=S+1;
113     rep(i,1,n1) if(i&1) insert(S,i,a[i]),insert(i,S,0);else insert(i,T,a[i]),insert(T,i,0);
114 
115     rep(i,1,m1) {
116     int x=gi(),y=gi();
117     if(a[x]==inf&&a[y]==inf) {
118         puts("-1");return 0;
119     }
120     insert(x,y,inf),insert(y,x,0);
121     }
122     double ans=0; 
123     while(bfs()) ans+=dfs(S,inf);
124     printf("%.1lf",ans);
125     return 0;
126 }
127 int gi() {
128     int res=0,f=1;
129     char ch=getchar();
130     while((ch<0||ch>9)&&ch!=-) ch=getchar();
131     if(ch==-) ch=getchar(),f=-1;
132     while(ch>=0&&ch<=9) res=res*10+ch-0,ch=getchar();
133     return res*f;
134 }

 

SDOI 保密