题意:自己看吧(不是很好说)

分析:

网络流:最大权闭合子图。

思路如下:

首先将点分为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]],而且只需要补上一次。

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

注:吐槽,我想说真的是神思路,加网络流大法好,我只想说没有刷过网络流24题的人伤不起啊

首先想会做这个题,必须会最大权闭合子图的概念,这个是网络流24题之一(多刷题就是好),但是就算是会了这个建图,也不一定会做这个题

虽然说这个题看数据范围什么的,限制条件这么多的,差不多能想到是网络流,但是伤在不会建图啊

这个题很巧妙的点,就是一个子序列的贡献是每两个不同点组成的,这是独立的,只和这两个元素有关,和序列的其它元素无关,这样每两个元素就可以虚拟一个点了

然后按照题解建成有向图,对于u-->v,选u必须选v 对于这种图的求最大方案,显然就是求最大权闭合图

如何建图,请见http://www.cnblogs.com/kane0526/archive/2013/04/05/3001557.html(可以顺便把这个题做一下,是个裸题)

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int maxn=4e4+;
struct Edge
{
int from,to,cap,flow;
Edge(int u,int v,int c,int d):from(u),to(v),cap(c),flow(d) {}
};
struct dinic
{
int s,t;
vector<Edge>edges;
vector<int>G[maxn];
int d[maxn];
int cur[maxn];
bool vis[maxn];
void init(){
for(int i=;i<maxn;++i)G[i].clear();
edges.clear();
}
bool bfs()
{
memset(vis,,sizeof(vis));
queue<int>q;
q.push(s);
d[s]=;
vis[s]=;
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=; i<G[x].size(); i++)
{
Edge &e= edges[G[x][i]];
if(!vis[e.to]&&e.cap>e.flow)
{
vis[e.to]=;
d[e.to]=d[x]+;
q.push(e.to);
}
}
}
return vis[t];
}
int dfs(int x,int a)
{
if(x==t||a==)return a;
int flow=,f;
for(int &i=cur[x]; i<G[x].size(); i++)
{
Edge &e=edges[G[x][i]];
if(d[x]+==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow))))
{
e.flow+=f;
edges[G[x][i]^].flow-=f;
flow+=f;
a-=f;
if(a==)break;
}
}
return flow;
}
LL maxflow(int s,int t)
{
this->s=s;
this->t=t;
LL flow=;
while(bfs())
{
memset(cur,,sizeof(cur));
flow+=dfs(s,INF);
}
return flow;
}
void addedge(int u,int v,int c)
{
Edge x(u,v,c,),y(v,u,,);
edges.push_back(x);
edges.push_back(y);
int l=edges.size();
G[u].push_back(l-);
G[v].push_back(l-);
}
}solve;
int a[],b[],T,n,w[][],kase;
char s[];
int main(){
scanf("%d",&T);
while(T--){
solve.init();
scanf("%d%s",&n,s+);
for(int i=;i<=;++i)
scanf("%d%d",&a[i],&b[i]);
for(int i=;i<=n;++i)
for(int j=;j<=n;++j)
scanf("%d",&w[i][j]);
int cnt=,p=n*(n-)/;
LL sum=;
for(int i=;i<n;++i){
for(int j=i+;j<=n;++j){
++cnt;
if(w[i][j]+w[j][i]>){
solve.addedge(,cnt,w[i][j]+w[j][i]);
sum+=w[i][j]+w[j][i];
}
solve.addedge(cnt,p+i,INF);
solve.addedge(cnt,p+j,INF);
}
}
int t=cnt+n+;
for(int i=;i<=n;++i){
if(a[s[i]-''+]>)
solve.addedge(cnt+i,t,a[s[i]-''+]);
solve.addedge(cnt+i,cnt+n+s[i]-''+,INF);
}
for(int i=cnt+n+;i<=cnt+n+;++i)
if(b[i-cnt-n]-a[i-cnt-n]>)
solve.addedge(i,t,b[i-cnt-n]-a[i-cnt-n]);
printf("Case #%d: %I64d\n",++kase,sum-solve.maxflow(,t));
}
return ;
}

HDU5772 String problem 最大权闭合图+巧妙建图的更多相关文章

  1. hdu 5772 String problem 最大权闭合子图

    String problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5772 Description This is a simple pro ...

  2. HDU5772 String problem(最大权闭合子图)

    题目..说了很多东西 官方题解是这么说的: 首先将点分为3类 第一类:Pij 表示第i个点和第j个点组合的点,那么Pij的权值等于w[i][j]+w[j][i](表示得分) 第二类:原串中的n个点每个 ...

  3. HDU5772 String problem

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission ...

  4. hdu5772-String problem(最大权闭合子图问题)

    解析: 多校标答 第一类:Pij 表示第i个点和第j个点组合的点,那么Pij的权值等于w[i][j]+w[j][i](表示得分)第二类:原串中的n个点每个点拆出一个点,第i个点权值为 –a[s[i]] ...

  5. 【算法系列学习】巧妙建图,暴搜去重 Counting Cliques

    E - Counting Cliques http://blog.csdn.net/eventqueue/article/details/52973747 http://blog.csdn.net/y ...

  6. 2018.10.30 NOIP模拟 有环无向图(dijkstra+巧妙建图)

    传送门 建图巧妙啊. 对于每个点的出边,我们将它们排序之后依次连边. 这样可以把O(m2)O(m^2)O(m2)的边数变成O(m)O(m)O(m)的了. 连的权值就是max(edgemax(edgem ...

  7. UVA1327 && POJ1904 King's Quest(tarjan+巧妙建图+强连通分量+缩点)

    UVA1327 King's Quest POJ1904 King's Quest 题意: 有n个王子,每个王子都有k个喜欢的妹子,每个王子只能和喜欢的妹子结婚.现有一个匹配表,将每个王子都与一个自己 ...

  8. TurtleBot3 Waffle (tx2版华夫)(12)建图-hector建图

    1)[Remote PC] 启动roscore $ roscore 2)[TurBot3] 启动turbot3 $ roslaunch turbot3_bringup minimal.launch 3 ...

  9. TurtleBot3 Waffle (tx2版华夫)(11)建图-karto建图

    1)[Remote PC] 启动roscore $ roscore 2)[TurBot3] 启动turbot3 $ roslaunch turbot3_bringup minimal.launch 3 ...

随机推荐

  1. nohup 程序名 & (使程序推到后台运行,即使终端关闭,该程序依然运行)

    IshallbeThatIshallbe:~ iamthat$ ps -ef |grep ping 502 450 1 0 9:30PM ?? 0:00.05 ping www.baidu.com 5 ...

  2. lintcode:二叉树的中序遍历

    题目: 二叉树的中序遍历 给出一棵二叉树,返回其中序遍历 样例 给出二叉树 {1,#,2,3}, 1 \ 2 / 3 返回 [1,3,2]. 挑战 你能使用非递归算法来实现么? 解题: 程序直接来源 ...

  3. Java学习笔记之:Java简介

    一.引言 Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计语言和Java平台的总称.由James Gosling和同事们共同研发,并在1995年正式推出. ...

  4. WCF入门(九)--WCF实例管理

    这组由Windows通讯基础(WCF)结合一组消息(客户端请求)服务实例所采用的技术被称为实例管理.一个完全由三种类型实例激活支持WCF,它们如下所述. 1.每个调用服务 每次调用服务是Windows ...

  5. linux 查看某一端口的占用情况

    查看某一端口的占用情况: lsof -i:端口号,例如查看端口21是否被占用 lsof -i: 实例:查看端口是否被占用,如果被占用结束掉该端口 [root@localhost splunk]# ls ...

  6. 【原创】30分钟入门 github

    很久没更新了,这篇文章重点在github的入门使用,读者可以下载github for windows shell,边看边操作,加深印象. 好了,30分钟的愉快之旅开始吧: 一.github使用的注意事 ...

  7. 车牌识别LPR(七)-- 字符特征

    第七篇:字符特征 选择的字符特征应该满足以下条件: (1)选取的字符特征具有较强的鲁棒性,不受字符变形.弯曲等影响. (2)两个字符的字符特征不能完全相同,但部分相同是允许的,即选择的字符特征是唯一的 ...

  8. IOSSelector的用法

    1.首先,@selector 里面的方法不能传参数..不要相信网上的..都是复制粘贴的.2.分三步走:1.设置tag.2.设置btn的调用方法.3.使用参数2.看示例代码把..   UIButton ...

  9. NLP基本任务-nltk_data文本分割

    将文本分割为句子 nltk.sent_tokenize(text,language) text:需要分割的文本 language:语言种类 czech捷克语 danish丹麦语 dutch荷兰语 en ...

  10. git cheat sheet,git四张手册图