zoukankan      html  css  js  c++  java
  • 【HDU5772】String Problem [网络流]

    String Problem

    Time Limit: 10 Sec  Memory Limit: 64 MB
    [Submit][Status][Discuss]

    Description

      

    Input

      

    Output

      

    Sample Input

      1
      3
      135
      1 2
      1 2
      1 2
      1 2
      1 2
      1 2
      1 2
      1 2
      1 2
      1 2
      0 0 3
      1 0 0
      4 0 0

    Sample Output

      3

    HINT

      

    Solution

      官方题解:

      首先将点分为3类

      第一类:Pij 表示第i个点和第j个点组合的点,那么Pij的权值等于w[i][j]+w[j][i](表示得到的价值

      第二类:原串中的n个点每个点拆出一个点,第i个点权值为 –a[s[i]] (表示需要的花费

      第三类:对于10种字符拆出10个点,每个点的权值为  -(b[x]-a[x])

      那么我们可以得到一个关系图 ,对于第一类中的点Pij,如果想要选择Pij,你就必须要选中第二类中的点i和j,对于第二类中的点如果你想选中第i个点,其对应的字符s[i],那么就必须选中第三类中s[i] 对应的点,因为每个种类的点第一次选中时花费是b[s[i]],而第二类中花费都是a[s[i]],一定要补上b[s[i]]-a[s[i]],而且只需要补上一次

      得到上面的关系图后然后就是普通的最大权闭合子图问题,直接求解即可。

      然后我们得到了若干关系,直接建边跑一边网络流即可。

    Code

      1 #include<iostream>  
      2 #include<string>  
      3 #include<algorithm>  
      4 #include<cstdio>  
      5 #include<cstring>  
      6 #include<cstdlib>  
      7 #include<cmath>  
      8 #include<ctime>
      9 using namespace std;  
     10 
     11 const int ONE = 200005;
     12 const int POI = 6005;
     13 const int INF = 2147483640;
     14 
     15 int Q,n;
     16 int S,T;
     17 char s[105];
     18 int Val[105][105];
     19 int next[ONE],first[POI],go[ONE],w[ONE],tot;
     20 int Dep[POI],q[ONE],E[POI],tou,wei;
     21 int part1,part2,part3;
     22 int Ans;
     23 
     24 struct power
     25 {
     26         int a,b;
     27 }a[15];
     28 
     29 int get() 
     30 {
     31         int res=1,Q=1;  char c;
     32         while( (c=getchar())<48 || c>57)
     33         if(c=='-')Q=-1;
     34         if(Q) res=c-48; 
     35         while((c=getchar())>=48 && c<=57) 
     36         res=res*10+c-48; 
     37         return res*Q; 
     38 }
     39 
     40 void Add(int u,int v,int z)
     41 {
     42         next[++tot]=first[u];   first[u]=tot;   go[tot]=v;  w[tot]=z;
     43         next[++tot]=first[v];   first[v]=tot;   go[tot]=u;  w[tot]=0;
     44 }
     45     
     46 int Bfs()
     47 {
     48         memset(Dep,0,sizeof(Dep));
     49         tou=0;  wei=1;
     50         q[1]=S; Dep[S]=1;
     51         for(int i=S;i<=T;i++) E[i]=first[i];
     52         while(tou<wei)
     53         {
     54             int u=q[++tou];
     55             for(int e=first[u];e;e=next[e])
     56             {
     57                 int v=go[e];
     58                 if(Dep[v] || !w[e]) continue;
     59                 Dep[v]=Dep[u]+1;
     60                 q[++wei]=v;
     61             }
     62         }
     63         return (Dep[T]>0);
     64 }
     65  
     66 int Dfs(int u,int Limit)
     67 {
     68         if(u==T || !Limit) return Limit;
     69         int from=0,f;
     70         for(int &e=E[u];e;e=next[e])
     71         {
     72             int v=go[e];
     73             if(Dep[v]!=Dep[u]+1 || !w[e]) continue;
     74             f=Dfs(v,min(Limit,w[e]));
     75             w[e]-=f;
     76             w[((e-1)^1)+1]+=f;
     77             Limit-=f;
     78             from+=f;
     79             if(!Limit) break;
     80         }
     81         return from; 
     82 }
     83 
     84 void Solve()
     85 {
     86         Ans = tot = 0;
     87         memset(first,0,sizeof(first));
     88         n=get();
     89         scanf("%s",s+1);
     90         for(int i=0;i<10;i++)
     91             a[i].a=get(), a[i].b=get();
     92         for(int i=1;i<=n;i++)
     93         for(int j=1;j<=n;j++)
     94             Val[i][j]=get(); 
     95         
     96         part1 = n*(n-1)/2;    part2 = n;    part3 = 10;
     97         S=0;    T= part1 + part2 + part3 +1;
     98         int num = 0;
     99         for(int i=1;i<=n;i++)
    100         for(int j=i+1;j<=n;j++)
    101         {
    102             num ++;    Ans += Val[i][j]+Val[j][i];
    103             Add(S,num, Val[i][j]+Val[j][i]);
    104             Add(num,part1+i, INF);
    105             Add(num,part1+j, INF);
    106         }
    107 
    108         for(int i=1;i<=n;i++)
    109         {
    110             Add(part1+i,T, a[s[i]-'0'].a);
    111             Add(part1+i,part1+part2+s[i]-'0'+1, INF);
    112         }
    113 
    114         for(int i=0;i<10;i++)
    115             Add(part1+part2+i+1,T, a[i].b-a[i].a);
    116 
    117         while(Bfs()) Ans-=Dfs(S,INF);
    118 
    119         printf("%d
    ",Ans);
    120 }
    121 
    122 int main()
    123 {
    124         Q=get();
    125         while(Q--)
    126             Solve();
    127 }
    View Code
  • 相关阅读:
    轻重搭配
    EF的优缺点
    使用bootstrap-select有时显示“Nothing selected”
    IIS发布 HTTP 错误 500.21
    js添加的元素无法触发click事件
    sql server查看表是否死锁
    sql server把一个库表的某个字段更新到另一张表的相同字段
    SQLSERVER排查CPU占用高的情况
    SQL server中如何按照某一字段中的分割符将记录拆成多条
    LINQ to Entities does not recognize the method 'System.DateTime AddDays(Double)' method, and this method cannot be translated into a store expression.
  • 原文地址:https://www.cnblogs.com/BearChild/p/6571177.html
Copyright © 2011-2022 走看看