POJ 3308 Paratroopers(最小点权覆盖+dinic算法)

第一个最小割,理解了好一会。

实数的最大流,注意eps,然后把乘法取log后变为加法。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cmath>
  4 #include <queue>
  5 using namespace std;
  6 #define eps 1e-8
  7 #define INF 0x3f3f3f3f
  8 int dis[201],first[201];
  9 int n,m,t;
 10 struct node
 11 {
 12     int u,v,next,re;
 13     double w;
 14 } edge[400001];
 15 void CL()
 16 {
 17     t = 1;
 18     memset(first,-1,sizeof(first));
 19 }
 20 void add(int u,int v,double w)
 21 {
 22     edge[t].u = u;
 23     edge[t].v = v;
 24     edge[t].w = w;
 25     edge[t].re = t+1;
 26     edge[t].next = first[u];
 27     first[u]  = t ++;
 28     edge[t].u = v;
 29     edge[t].v = u;
 30     edge[t].w = 0;
 31     edge[t].re = t-1;
 32     edge[t].next = first[v];
 33     first[v] = t ++;
 34 }
 35 int bfs()
 36 {
 37     int u,i,v;
 38     memset(dis,-1,sizeof(dis));
 39     queue<int> que;
 40     que.push(0);
 41     dis[0] = 0;
 42     while(!que.empty())
 43     {
 44         u = que.front();
 45         que.pop();
 46         for(i = first[u]; i != -1; i = edge[i].next)
 47         {
 48             v = edge[i].v;
 49             if(edge[i].w > eps&&dis[v] < 0)
 50             {
 51                 dis[v] = dis[u]+1;
 52                 que.push(v);
 53             }
 54         }
 55     }
 56     if(dis[n+m+1] > 0) return 1;
 57     else  return 0;
 58 }
 59 double dfs(int u,double step)
 60 {
 61     int i,v;
 62     double temp;
 63     if(u == n+m+1) return step;//n+m+1是汇点
 64     for(i = first[u]; i != -1; i = edge[i].next)
 65     {
 66         v = edge[i].v;
 67         if(edge[i].w > eps&&dis[v] == dis[u]+1&&(temp = dfs(v,min(step,edge[i].w))))
 68         {
 69             edge[i].w -= temp;
 70             edge[edge[i].re].w += temp;
 71             return temp;
 72         }
 73     }
 74     return 0;
 75 }
 76 int main()
 77 {
 78     int i,l,cas,sv,ev;
 79     double temp,ans,res;
 80     scanf("%d",&cas);
 81     while(cas--)
 82     {
 83         CL();
 84         scanf("%d%d%d",&n,&m,&l);
 85         for(i = 1; i <= n; i ++)
 86         {
 87             scanf("%lf",&temp);
 88             add(0,i,log(temp));
 89         }
 90         for(i = 1; i <= m; i ++)
 91         {
 92             scanf("%lf",&temp);
 93             add(n+i,n+m+1,log(temp));
 94         }
 95         for(i = 1; i <= l; i ++)
 96         {
 97             scanf("%d%d",&sv,&ev);
 98             add(sv,n+ev,INF);
 99         }
100         ans = 0;
101         while(bfs())
102         {
103             res = dfs(0,INF);//注意0是源点
104             if(res > eps)
105             ans += res;
106             else
107             break;//注意这里
108         }
109         printf("%.4f\n",exp(ans));
110     }
111     return 0;
112 }

 

转载于:https://www.cnblogs.com/naix-x/archive/2013/04/17/3026281.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值