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
  • 相关阅读:
    python判断字典中key是否存在
    获取redis中所有的key,清空整个 Redis 服务器的数据
    python redis模块详解
    Windows中redis的下载及安装、设置
    .htaccess
    python介绍
    vi和vim
    其他
    Linux系统相关命令
    Linux用户权限常见命令
  • 原文地址:https://www.cnblogs.com/BearChild/p/6571177.html
Copyright © 2011-2022 走看看