zoukankan      html  css  js  c++  java
  • poj 3308(最小割+对数处理)

    这题有一个非常坑人的地方,  product 这个单词在这题里是 “相乘"  的意思.   

    然后就是最小割模型的建立,s=0,t=m+n+1 然后从s到1-m建权为Ci一条边,从 m+1 - m+n 建立到t的权值为Ri的边。 然后每个伞兵的坐标(x,y) 建立x->y权为无穷大的边.   

    这题关键的一点叫我们求所有费用的乘积最小,可以知道的是用最小割模型求出的是所有费用的和, 如果想处理乘法运算看似很难办, 但是有一种很灵巧的方法:

    将每条边的权值先取对数(log是以e为底,log10是以10为底),然后其中网络流中的操作都为+-,对于对数就相当于乘除, 可知如果最后求出去对数后的权值和最大,然后exp(e的平方)一下就可以得到最大的总乘积. 

    以后遇到乘法难以处理时,想想用对数转化为+- 的运算是否可以解决.

    Paratroopers
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 5432   Accepted: 1617

    Description

    It is year 2500 A.D. and there is a terrible war between the forces of the Earth and the Mars. Recently, the commanders of the Earth are informed by their spies that the invaders of Mars want to land some paratroopers in the × n grid yard of one their main weapon factories in order to destroy it. In addition, the spies informed them the row and column of the places in the yard in which each paratrooper will land. Since the paratroopers are very strong and well-organized, even one of them, if survived, can complete the mission and destroy the whole factory. As a result, the defense force of the Earth must kill all of them simultaneously after their landing.

    In order to accomplish this task, the defense force wants to utilize some of their most hi-tech laser guns. They can install a gun on a row (resp. column) and by firing this gun all paratroopers landed in this row (resp. column) will die. The cost of installing a gun in the ith row (resp. column) of the grid yard is ri (resp. ci ) and the total cost of constructing a system firing all guns simultaneously is equal to the product of their costs. Now, your team as a high rank defense group must select the guns that can kill all paratroopers and yield minimum total cost of constructing the firing system.

    Input

    Input begins with a number T showing the number of test cases and then, T test cases follow. Each test case begins with a line containing three integers 1 ≤ m ≤ 50 , 1 ≤ n ≤ 50 and 1 ≤ l ≤ 500 showing the number of rows and columns of the yard and the number of paratroopers respectively. After that, a line with m positive real numbers greater or equal to 1.0 comes where the ith number is ri and then, a line with n positive real numbers greater or equal to 1.0 comes where the ith number is ci. Finally, l lines come each containing the row and column of a paratrooper.

    Output

    For each test case, your program must output the minimum total cost of constructing the firing system rounded to four digits after the fraction point.

    Sample Input

    1
    4 4 5
    2.0 7.0 5.0 2.0
    1.5 2.0 2.0 8.0
    1 1
    2 2
    3 3
    4 4
    1 4

    Sample Output

    16.0000

    Source

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <math.h>
      4 #include <string>
      5 #include <iostream>
      6 using namespace std;
      7 #define N 110
      8 #define M 5*N*N
      9 #define INF 0x3ffffff
     10 
     11 struct node
     12 {
     13     int to,next;
     14     double w;
     15 }edge[M];
     16 
     17 int cnt,pre[N];
     18 int s,t;
     19 int nn;
     20 int n,m;
     21 int lv[N],gap[N];
     22 
     23 void add_edge(int u,int v,double w)
     24 {
     25     edge[cnt].to=v;
     26     edge[cnt].w=w;
     27     edge[cnt].next=pre[u];
     28     pre[u]=cnt++;
     29 }
     30 
     31 double sdfs(int k,double w)
     32 {
     33     if(k==t) return w;
     34     double f=0;
     35     int mi=nn-1;
     36     for(int p=pre[k];p!=-1;p=edge[p].next)
     37     {
     38         int v=edge[p].to;
     39         if(edge[p].w!=0)
     40     {
     41             if(lv[k]==lv[v]+1)
     42             {
     43                 double tmp=sdfs(v,min(w-f,edge[p].w));
     44                 f+=tmp;
     45                 edge[p].w-=tmp;
     46                 edge[p^1].w+=tmp;
     47                 if(f==w||lv[s]==nn) return f;
     48             }
     49             if(lv[v]<mi) mi=lv[v];
     50         }
     51     }
     52     if(f==0)
     53     {
     54         gap[lv[k]]--;
     55         if(gap[lv[k]]==0)
     56         {
     57             lv[s]=nn;
     58             return f;
     59         }
     60         lv[k]=mi+1;
     61         gap[lv[k]]++;
     62     }
     63     return f;
     64 }
     65 
     66 double sap()
     67 {
     68     nn=t+1;
     69     double sum=0;
     70     memset(lv,0,sizeof(lv));
     71     memset(gap,0,sizeof(gap));
     72     gap[0]=nn;
     73     while(lv[s]<nn)
     74     {
     75         sum+=sdfs(s,INF);
     76     }
     77     return sum;
     78 }
     79 int main()
     80 {
     81     int t1,p;
     82     scanf("%d",&t1);
     83     while(t1--)
     84     {
     85         cnt=0;
     86         memset(pre,-1,sizeof(pre));
     87         scanf("%d%d%d",&n,&m,&p);
     88         s=0;
     89         t=n+m+1;
     90         for(int i=1;i<=n;i++)
     91         {
     92             double w;
     93             scanf("%lf",&w);
     94             add_edge(s,i,log(w));
     95             add_edge(i,s,0);
     96         }
     97         for(int i=1;i<=m;i++)
     98         {
     99             double  w;
    100             scanf("%lf",&w);
    101             add_edge(n+i,t,log(w));
    102             add_edge(t,n+i,0);
    103         }
    104         for(int i=0;i<p;i++)
    105         {
    106             int x,y;
    107             scanf("%d%d",&x,&y);
    108             add_edge(x,n+y,INF);
    109             add_edge(n+y,x,0);
    110         }
    111         printf("%.4lf\n",exp(sap()));
    112     }
    113     return 0;
    114 }
  • 相关阅读:
    父子传值
    第三次作业
    第二次作业
    最后一次作业--总结报告
    Vue项目axios请求设置responseType无效
    滚动条样式修改
    超出部分显示省略号,鼠标悬浮显示详细文本,el-tooltip
    大屏rem
    js比较时间大小
    kindeditor编辑器上传图片跨域
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/2910820.html
Copyright © 2011-2022 走看看