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 }

 

你可能感兴趣的:(dinic)