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的情况。

  • 相关阅读:
    如何在Android Studio中添加注释模板信息?
    Android Activity标签属性
    Android Activity全面解析
    Mac office ppt无法正常输入文字的问题解决方案
    将Android Studio默认布局ConstraintLayout切换成LinearLayout
    Java中Double保留后小数位的几种方法
    java文件传输接口
    纯JS编写打地鼠游戏
    JavaScript监听手机物理返回键的两种解决方法
    spring注解方式实现定时器
  • 原文地址:https://www.cnblogs.com/TenderRun/p/5750765.html
Copyright © 2011-2022 走看看