缩点+染色+DFS codeforce467D
题目链接:https://vjudge.net/contest/219056#problem/A
推荐博客:https://blog.csdn.net/ck_boss/article/details/39429285
发现上面的这位大佬的思路和我一样,自己代码太多错误就参考了一下。
题意:
输入n,接下来会输入输入n个字符串,然后输入m,接下来会输入m对字符串,每一对表示左边的字符串可以变成右边的字符串,但是右边的不可以变成左边的。字符串不论大小写,现在要我们经过变换把一开始的n个字符里面的字符 ' r'或'R'(不分大小写,你全部改成大写或小写)最少,如果有多个r最少,那么就换成总长度最短的,输出r的个数和总长度。
额,网上大多数好像使用BFS写的,但是我写得时候因为在做图论的题,就强行联想到了tarjan算法,然后就不想换思路,就用tarjan加DFS写了,代码比较长而且比较难看,先说一下思路,有兴趣的可以看代码,虽然比较。。。
思路就是先tarjan缩点,把可以两两相互替换的字符串(在同一个强连通分量里面)缩点染色,同时记录这个强连通分量里面最小的r个数和对于最短的长度。之后把缩完的点二次建图,最后用DFS找答案。
代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<cmath>
#include<vector>
#include<set>
#include<cstdio>
#include<string>
#include<deque>
using namespace std;
typedef long long LL;
#define eps 1e-8
#define INF 0x3f3f3f3f
#define maxn 100005
struct node{
int value,length;
}dot[maxn],min1[maxn];//dot数字记录每个字符串编号之后对应的值
//min1数组记录染色之后每个强连通分量里面最符合的值
struct EDGE{
int v,next;
}edge[maxn],edge2[maxn];//这里要两次建图,一次是给字符串编号之后建图,还有一次是缩点之后重新建图
int a[maxn];
int head[maxn],head2[maxn];
int dfn[maxn],low[maxn],color[maxn],s[maxn];
int n,m,k,t;
int cnt,time,ans,id,top,num,cnt2;
map<string,int>mp;//给每个字符串编号
map<pair<int,int>,int>mmp;//重新建图的时候防止重复的边
bool vis[maxn];
void init()
{
mmp.clear();
mp.clear();
memset(head,-,sizeof(head));
memset(dfn,,sizeof(dfn));
memset(head2,-,sizeof(head2));
cnt=time=ans=id=top=num=;
memset(vis,false,sizeof(vis));
cnt2=;
for(int i=;i<maxn;i++)
{
min1[i].length=min1[i].value=INF;
}
}
void cal(string &s)//编号并计算r的个数和字符串长度
{
mp[s]=++id;
int value=;
for(int i=;i<s.size();i++)
{
if(s[i]=='r')
value++;
}
dot[mp[s]].value=value;//dot记录字符串s对应编号的r个数和长度
dot[mp[s]].length=s.size();
}
void tarjan(int u)//缩点染色
{
dfn[u]=low[u]=++time;
s[top++]=u;
vis[u]=true;
for(int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].v;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],dfn[v]);
}
else if(vis[v])//必须要在栈内,因为这里不一定是一个连通图,所以一定要判断是否在栈内
//并且一定要写成dfn[v],不能写成low[u]
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
ans++;
int v;
do{
v=s[--top];
vis[v]=false;
color[v]=ans;
if(dot[v].value<min1[ans].value||dot[v].value==min1[ans].value&&dot[v].length<min1[ans].length)
{
//min1数组记录每个强连通分量里面最优的结果
min1[ans].value=dot[v].value;
min1[ans].length=dot[v].length;
}
}while(v!=u);
}
}
void addedge(int u,int v)
{
edge[++cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt;
}
void addedge2(int u,int v)
{
edge2[++cnt2].v=v;
edge2[cnt2].next=head2[u];
head2[u]=cnt2;
}
void get_edge2()
{
for(int i=;i<=id;i++)
{
for(int j=head[i];j!=-;j=edge[j].next)
{
int v=edge[j].v;
if(color[i]!=color[v]&&mmp[make_pair(color[i],color[v])]==)
{
addedge2(color[i],color[v]);
mmp[make_pair(color[i],color[v])]=;
}//两个强连通分量之间建一条有向图,可能有重复边,我们用mmp记录去掉
}
}
}
node bijiao(node s1,node s2)
{
if(s1.value<s2.value||s1.value==s2.value&&s1.length<s2.length)
return s1;
return s2;
}
void DFS(LL u)
{
if(vis[u])
return;
vis[u]=true;
for(int i=head2[u];i!=-;i=edge2[i].next)
{
int v=edge2[i].v;
if(!vis[v])
DFS(v);
min1[u]=bijiao(min1[u],min1[v]);
}
return;
}
string ope(string str)
{
for(int j=;j<str.size();j++)
{
if(str[j]>='A'&&str[j]<='Z')//全部变成小写
str[j]=str[j]-'A'+'a';
}
return str;
}
int main()
{
while(cin>>n)
{
init();
string str;
for(int i=;i<n;i++)
{
cin>>str;
str=ope(str);
if(mp[str]==)//编号
cal(str);
a[i]=mp[str];//记录文章里面字符串的编号
}
cin>>m;
string s1,s2;
for(int i=;i<m;i++)
{
cin>>s1>>s2;
s1=ope(s1);
s2=ope(s2);
if(mp[s1]==)
cal(s1);
if(mp[s2]==)
cal(s2);
addedge(mp[s1],mp[s2]);//建图,从s1的编号到s2的编号的有向边
}
for(int i=;i<=id;i++)//求强连通分量
{
if(!dfn[i])
tarjan(i);
}
get_edge2();//缩点之后重新建图
LL sum1=,sum2=;
int flag[maxn];
memset(vis,false,sizeof(vis));
memset(flag,,sizeof(flag));
//DFS(c);//试了无数次,不知道这句为什么放在这里就错了 ,不然可以节省很多时间
for(int i=;i<n;i++)
{
LL c=color[a[i]];
if(!flag[c])
{
memset(vis,,sizeof(vis));
DFS(c);//不知道为啥放在这里就对了
flag[c]=;
}
sum1+=min1[c].value;
sum2+=min1[c].length;
}
cout<<sum1<<' '<<sum2<<endl;
}
return ;
}
缩点+染色+DFS codeforce467D的更多相关文章
- hihoCoder 1185 连通性·三(Tarjan缩点+暴力DFS)
#1185 : 连通性·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 暑假到了!!小Hi和小Ho为了体验生活,来到了住在大草原的约翰家.今天一大早,约翰因为有事要出 ...
- hdu 3478 Catch(染色 dfs 或 bfs )
Problem Description A thief is running away! We can consider the city to N–. The tricky thief starts ...
- uva 193 Graph Coloring(图染色 dfs回溯)
Description You are to write a program that tries to find an optimal coloring for a given graph. Col ...
- UVA 193 Graph Coloring 图染色 DFS 数据
题意:图上的点染色,给出的边的两个点不能都染成黑色,问最多可以染多少黑色. 很水的一题,用dfs回溯即可.先判断和当前点相连的点是否染成黑色,看这一点是否能染黑色,能染色就分染成黑色和白色两种情况递归 ...
- poj 2553 缩点+染色+出度
题目链接:https://vjudge.net/problem/POJ-2553 如果不会tarjan算法,推荐博客:https://blog.csdn.net/mengxiang000000/art ...
- [POI2010] GIL-Guilds - 二分图染色,DFS
给一张无向图,要求你用黑白灰给点染色,且满足对于任意一个黑点,至少有一个白点和他相邻:对于任意一个白点,至少有一个黑点与他相邻,对于任意一个灰点,至少同时有一个黑点和白点和灰点与他相邻,问能否成功 S ...
- HDU 3639 Hawk-and-Chicken(Tarjan缩点+反向DFS)
Problem Description Kids in kindergarten enjoy playing a game called Hawk-and-Chicken. But there alw ...
- Paint the Grid Reloaded(缩点,DFS+BFS)
Leo has a grid with N rows and M columns. All cells are painted with either black or white initially ...
- CF 272E Dima and Horses 染色,dfs 难度:2
http://codeforces.com/problemset/problem/272/E 把仇恨关系想象为边, 因为度只能为0,1,2,3,所以有以下几种 0,1 直接放即可 2: 有(1,1), ...
随机推荐
- Flex Iris效果放大或缩小组件演示
Iris效果通过扩展或收缩集中在目标上的矩形遮罩为效果目标设置动画.该效果可以从目标的中心放大遮罩来显示目标,也可以向中心收缩遮罩来隐藏目标.演示: 源码如下: <?xml version=&q ...
- OV7670配置和调试小结
先上一下OV7670的框架图 OV7670常用寄存器设置说明 直接看OV7670 Implementation Guide (V1.0)等 资料我已经上传了 https://files.cnblogs ...
- office转pdf转swf
系统环境:CentOs5.5用到的工具:Openoffice 3 , Pdf2Swf tool , Jodconverter , FlexPaper 网上找了些资料,早有人已经实现了这样的功能,只不过 ...
- PHP5 的五种常用模式
PHP5 的五种常用模式. 工厂模式 最初在设计模式 一书中,许多设计模式都鼓励使用松散耦合.要理解这个概念,让我们最好谈一下许多开发人员从事大型系统的艰苦历程.在更改一个代码片段时,就会发生问题,系 ...
- 深度学习原理与框架-Tensorflow卷积神经网络-神经网络mnist分类
使用tensorflow构造神经网络用来进行mnist数据集的分类 相比与上一节讲到的逻辑回归,神经网络比逻辑回归多了隐藏层,同时在每一个线性变化后添加了relu作为激活函数, 神经网络使用的损失值为 ...
- 机器学习进阶-图像梯度计算-scharr算子与laplacian算子(拉普拉斯) 1.cv2.Scharr(使用scharr算子进行计算) 2.cv2.laplician(使用拉普拉斯算子进行计算)
1. cv2.Scharr(src,ddepth, dx, dy), 使用Scharr算子进行计算 参数说明:src表示输入的图片,ddepth表示图片的深度,通常使用-1, 这里使用cv2.CV_6 ...
- DMA/Zero copy
DMA: 直接内存访问,是一种不经过CPU而直接从内存存取数据的数据交换模式.在DMA模式下,CPU只须向DMA控制器下达指令,让DMA控制器来处理数据的传送,数据传送完毕再把信息反馈给CPU,这样就 ...
- UNITY2018.3 在editor下运行时new memoryprofiler显示 shader占用内存很大的问题在安卓上并没有看到
在安卓机上完全看不到shader占用的内存,但问题是,shader在安卓上真的几乎不占用内存了?(我们的游戏中只使用了mobile下的shader) 参考下面这个文章,说是真机上也有: Unity3D ...
- 使用jQuery+huandlebars遍历数组
兼容ie8(很实用,复制过来,仅供技术参考,更详细内容请看源地址:http://www.cnblogs.com/iyangyuan/archive/2013/12/12/3471227.html) & ...
- C# 汉字转拼音(全拼)
C# 汉字转拼音(全拼) 很多时候我们需要把汉字转换成拼音,比如姓名.城市名等.网上搜索了一把,把汉字转成拼音的代码很多,但大多都只是把汉字转成了拼音的首字母,比如把“深圳”转成了“sz”.那 ...