zoukankan      html  css  js  c++  java
  • 图论(网络流):UVa 1659

    Laura Luo has just invented a game. Given a beautiful pencil sketch with n points, you're to colorize it with water pens by painting circuits. Each time you paint a new circuit, starts with one point, follow some line segments and return to the starting point. Every point can be reached more than once, but every segment can be painted at most once. To make the picture look interesting, different segments must be painted different colors. For each segment, Laura has already decided a direction to paint it. The picture below illustrates a possible way to paint the picture (dashed lines are segments that are not painted).

    epsfbox{p4030.eps}

    After you finish painting, your score is computed as follows: for each unit length you paint, you earn x points, for each color you use, you lost y points (Laura has prepared enough water pens of different colors).

    Write a program to find the maximal score you can get.

    Input 

    The input contains several test cases. The first line of each case contains three positive integers n, x, y (1$ le$n$ le$100, 1$ le$x, y$ le$1000) . The next n lines each describe a point (points are numbered from 1 to n in the order they appear in the input). The first two integers (x, y) specify its coordinates (0$ le$x, y$ le$1000) . The rest integers are the points it connects to, ended by a zero. If point v appears in the list of point u , there is a line segment connecting u and v (then there will not a segment connecting u and v in the reverse direction). Furthermore, Laura will paint it from u to v . There will be no duplicated points and no more than 500 segments. The last test case is followed by a single zero, which should not be processed.

    Output 

    For each test case, print the case number and the maximal score you can get, to two decimal places.

    Sample Input 

    4 5 1 
    0 0 2 3 0 
    1 0 3 4 0 
    1 1 4 0 
    0 1 1 0 
    1 2 1 
    0 0 0 
    10 7 2 
    0 0 2 4 0 
    5 0 3 0 
    5 10 4 10 0 
    2 3 5 0 
    7 5 6 0 
    0 11 1 0 
    8 0 10 5 0 
    18 3 7 0 
    14 5 8 1 0 
    12 9 9 0 
    0
    

    Sample Output 

    Case 1: 16.00

    Case 2: 0.00

    Case 3: 522.18

      

      这道题就是最小费用循环流的模板,先上代码。

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <queue>
     5 #include <cmath>
     6 using namespace std;
     7 const int N=110;
     8 const int M=20010;
     9 const int INF=1061109567;
    10 const double dINF=1e9;
    11 const double eps=1e-6;
    12 int w[N],cnt,fir[N],to[M],nxt[M];
    13 int cap[M],path[N],vis[N];
    14 double val[M],dis[N];
    15 queue<int>q;
    16 struct Net_Flow{
    17     void Init(){memset(fir,0,sizeof(fir));cnt=1;}
    18     
    19     void add(int a,int b,int c,double v){
    20         nxt[++cnt]=fir[a];cap[cnt]=c;
    21         to[cnt]=b;val[cnt]=v;fir[a]=cnt;
    22     }
    23     
    24     void addedge(int a,int b,int c,double v){
    25         add(a,b,c,v);add(b,a,0,-v);
    26     }
    27     
    28     double Spfa(int S,int T){
    29         fill(dis,dis+T+1,dINF);
    30         q.push(S);vis[S]=1;dis[S]=0;
    31         while(!q.empty()){
    32             int x=q.front();q.pop();vis[x]=0;
    33             for(int i=fir[x];i;i=nxt[i])
    34                 if(cap[i]&&dis[to[i]]-dis[x]-val[i]>eps){
    35                     dis[to[i]]=dis[x]+val[i];
    36                     if(!vis[to[i]])q.push(to[i]);
    37                     vis[to[i]]=1;path[to[i]]=i;
    38                 }
    39         }
    40         return dis[T];
    41     }
    42     
    43     int Aug(int S,int T){
    44         int p=T,f=INF;
    45         while(p!=S){
    46             f=min(f,cap[path[p]]);
    47             p=to[path[p]^1];
    48         }p=T;
    49         while(p!=S){
    50             cap[path[p]]-=f;
    51             cap[path[p]^1]+=f;
    52             p=to[path[p]^1];
    53         }
    54         return f;
    55     }
    56     
    57     double MCMF(int S,int T){
    58         double v=0,d;
    59         while((d=Spfa(S,T))!=dINF)
    60             v+=d*Aug(S,T);
    61         return v;
    62     }
    63 }mcmf;
    64 int deg[N];
    65 int a[N],b[N],G[N][N];
    66 int sqr(int x){
    67     return x*x;
    68 }
    69 int main(){
    70     int n,x,y,cas=0;double ans;
    71     while(scanf("%d%d%d",&n,&x,&y)!=EOF){
    72         if(!n)break;
    73         mcmf.Init();ans=0.0;
    74         memset(G,0,sizeof(G));
    75         memset(deg,0,sizeof(deg));
    76         for(int i=1;i<=n;i++){
    77             int t;
    78             scanf("%d%d%d",&a[i],&b[i],&t);
    79             while(t){G[i][t]=1;scanf("%d",&t);}
    80         }
    81         for(int i=1;i<=n;i++)
    82             for(int j=1;j<=n;j++)if(G[i][j]){
    83                 double v=y-x*sqrt(sqr(a[i]-a[j])+sqr(b[i]-b[j]));    
    84                 if(v<0){
    85                     mcmf.addedge(j,i,1,-v);
    86                     ans+=v;deg[j]+=1;deg[i]-=1;
    87                 }
    88                 if(v>0)mcmf.addedge(i,j,1,v);
    89             }
    90                 
    91         for(int i=1;i<=n;i++){
    92             if(deg[i]>0)mcmf.addedge(0,i,deg[i],0);
    93             if(deg[i]<0)mcmf.addedge(i,n+1,-deg[i],0);
    94         }
    95         printf("Case %d: %.2f
    ",++cas,eps-ans-mcmf.MCMF(0,n+1));
    96     }
    97     return 0;
    98 }
      具体就如代码,网络流还是一般的网络流,就是建边很神。
      最后的eps是为了防止输出-0.00的情况。

  • 相关阅读:
    51nod 1574 排列转换(猜结论)
    百度之星资格赛 1005 寻找母串(分块打表+组合数计算)
    百度之星资格赛 1004 度度熊的午饭时光(01背包+最小序号和+字典序+有bug)
    百度之星资格赛 1003 度度熊与邪恶大魔王(二维dp)
    HDU 4542 小明系列故事——未知剩余系 (数论|反素数)
    51nod 1060 最复杂的数(反素数)
    eclipse hadoop环境搭建 查看HDFS文件内容
    Windows jdk安装以及版本切换
    WIN10配置MongoDB
    Oracle 11g R2 for Win10(64位)的安装步骤
  • 原文地址:https://www.cnblogs.com/TenderRun/p/5750765.html
Copyright © 2011-2022 走看看