zoukankan      html  css  js  c++  java
  • 【Foreign】猜测 [费用流]

    猜测

    Time Limit: 10 Sec  Memory Limit: 256 MB

    Description

      

    Input

      

    Output

      

    Sample Input

      3
      1 1
      1 2
      2 1

    Sample Output

      3
      explain:
      (1,1),(1,1),(2,2)不是一个合法猜测(有相同的格子),因此不管怎么猜总是能全部猜中。

    HINT

      

    Main idea

      给定了若干个标准点,用这些点的横纵坐标分为x集和y集,定义猜点表示从x集和y集中各选一个,不能猜出重复的点,问在所有合法方案中最少包含上述几个标准点。

    Solution

      我们看到了这道题目,考虑从费用流的方法下手。

      我们从S->x集:容量为数字出现次数,费用为0y集->T:容量为数字出现次数,费用为0x集->y集:容量为1,若组合成了标准点则费用为1,否则为0

      然后我们这样连边,又由于题目要的是最少包含几个点,那么显然最小费用最大流就是答案了。

    Code

      1 #include<iostream>  
      2 #include<algorithm>  
      3 #include<cstdio>  
      4 #include<cstring>  
      5 #include<cstdlib>  
      6 #include<cmath>  
      7 using namespace std;
      8 
      9 const int ONE = 2000001;
     10 const int INF = 2147483640;
     11 
     12 int n,x,y;
     13 int S,T;
     14 int E[1001][1001];
     15 int next[ONE],first[ONE],go[ONE],pas[ONE],Fro[ONE],tot=1;
     16 int from[ONE],q[1000001],dist[200001];
     17 bool vis[ONE];
     18 int tou,wei;
     19 int Ans,w[ONE];
     20 int li[ONE],li_num;
     21 
     22 struct power
     23 {
     24         int x,y;
     25 }a[ONE],time[ONE],Max;
     26 
     27 int get() 
     28 { 
     29         int res,Q=1;    char c;
     30         while( (c=getchar())<48 || c>57)
     31         if(c=='-')Q=-1;
     32         if(Q) res=c-48; 
     33         while((c=getchar())>=48 && c<=57) 
     34         res=res*10+c-48; 
     35         return res*Q; 
     36 }
     37 
     38 void Add(int u,int v,int liu,int z)
     39 {
     40         next[++tot]=first[u];   first[u]=tot;   go[tot]=v;  w[tot]=z;   pas[tot]=liu;   Fro[tot]=u;
     41         next[++tot]=first[v];   first[v]=tot;   go[tot]=u;  w[tot]=-z;  pas[tot]=0;     Fro[tot]=v;
     42 } 
     43 
     44 int Bfs()
     45 {
     46         memset(dist,63,sizeof(dist));
     47         dist[S]=0;  q[1]=S; vis[S]=1;
     48         tou=0;  wei=1;
     49         while(tou<wei)
     50         {
     51             int u=q[++tou];
     52             for(int e=first[u];e;e=next[e])
     53             {
     54                 int v=go[e];
     55                 if(dist[v]>dist[u]+w[e] && pas[e])
     56                 {
     57                     dist[v]=dist[u]+w[e]; from[v]=e;
     58                     if(!vis[v])
     59                     {
     60                         q[++wei]=v;
     61                         vis[v]=1;
     62                     }
     63                 }
     64             }
     65             vis[u]=0;
     66         }
     67         return dist[T]!=dist[T+10];
     68 }
     69 
     70 void Deal()
     71 {
     72         int x=INF;
     73         for(int e=from[T];e;e=from[Fro[e]]) x=min(x,pas[e]);
     74         for(int e=from[T];e;e=from[Fro[e]])
     75         {
     76             pas[e]-=x;
     77             pas[e^1]+=x;
     78             Ans += w[e]*x;
     79         }
     80 }
     81 
     82 int main()
     83 {
     84         n=get();
     85         for(int i=1;i<=n;i++)
     86         {
     87             a[i].x=get();    a[i].y=get();
     88             li[++li_num]=a[i].x; li[++li_num]=a[i].y;
     89         }
     90         
     91         sort(li+1,li+li_num+1);
     92         li_num = unique(li+1,li+li_num+1) - li - 1;
     93         S=0;    T=2*li_num+1;
     94         
     95         for(int i=1;i<=n;i++)
     96         {
     97             a[i].x = lower_bound(li+1,li+li_num+1, a[i].x) - li;
     98             a[i].y = lower_bound(li+1,li+li_num+1, a[i].y) - li;
     99             E[ a[i].x ][ a[i].y ] = 1;
    100             time[a[i].x].x++;            time[a[i].y].y++;
    101             Max.x = max(Max.x, a[i].x);    Max.y = max(Max.y, a[i].y);
    102         }
    103         
    104         for(int i=1;i<=Max.x;i++) if(time[i].x) Add(S,i,time[i].x,0);
    105         for(int i=1;i<=Max.y;i++) if(time[i].y) Add(i+Max.x,T,time[i].y,0);
    106         
    107         for(int i=1;i<=Max.x;i++)
    108         if(time[i].x)
    109         for(int j=1;j<=Max.y;j++)
    110         if(time[j].y)
    111         {
    112             if(E[i][j]) Add(i,j+Max.x,1,1);
    113             else Add(i,j+Max.x,1,0);
    114         }
    115         
    116         while(Bfs()) Deal();
    117         
    118         printf("%d",Ans);
    119         
    120 }
    View Code

     

  • 相关阅读:
    来实现一个缩水版Vuex
    vue中的适配:px2rem
    Vue.js的复用组件开发流程
    Vue调试神器之Vue.js devTools
    浅析Vue响应式原理(三)
    逐行粒度的vuex源码分析
    vue源码解读-目录结构
    Vue源码探究-虚拟DOM的渲染
    利用hash或history实现单页面路由
    passive的作用和原理
  • 原文地址:https://www.cnblogs.com/BearChild/p/6501739.html
Copyright © 2011-2022 走看看