Codeforces 467D. Fedor and Essay (Graphs,dfs,dp,hashing,strings,图论综合型好题)
来源:互联网 发布:程序员思维笑话 编辑:程序博客网 时间:2024/05/16 08:02
题目地址:http://codeforces.com/contest/467/problem/D
别怪我=。=
我本来是写好了题解的,结果按错一个键,题解没有保存下来。
懒,不写了。总的来说方法就是标题所列,那也是codeforces上tag所给
方法如下:
hashing + strings: 有效hash处理字符串,将字符串转换为点,方便图形处理(要以字符串种类为基建图,否则边会太多,数组存不下
graphs: 图论,用到建图等图论知识
SCC: 强联通分量,将图转换为有向无环图(直接处理图会出错,必须转换为有向无环图
dfs+dp: 在有向无环图上进行dfs,在dfs基础上dp,进行搜索
最后统计答案即可
看不懂就抱歉了,不小心没保存题解
据说这题有更好的方法?我要去学学,哪天心血来潮再把题解补上吧=。=!
//Hello. I'm Peter.#include<cstdio>#include<iostream>#include<sstream>#include<cstring>#include<string>#include<cmath>#include<cstdlib>#include<algorithm>#include<functional>#include<cctype>#include<ctime>#include<stack>#include<queue>#include<vector>#include<set>#include<map>using namespace std;typedef long long ll;typedef long double ld;#define peter cout<<"i am peter"<<endl#define input freopen("data.txt","r",stdin)#define randin srand((unsigned int)time(NULL))#define INT (0x3f3f3f3f)*2#define LL (0x3f3f3f3f3f3f3f3f)*2#define gsize(a) (int)a.size()#define len(a) (int)strlen(a)#define slen(s) (int)s.length()#define pb(a) push_back(a)#define clr(a) memset(a,0,sizeof(a))#define clr_minus1(a) memset(a,-1,sizeof(a))#define clr_INT(a) memset(a,INT,sizeof(a))#define clr_true(a) memset(a,true,sizeof(a))#define clr_false(a) memset(a,false,sizeof(a))#define clr_queue(q) while(!q.empty()) q.pop()#define clr_stack(s) while(!s.empty()) s.pop()#define rep(i, a, b) for (int i = a; i < b; i++)#define dep(i, a, b) for (int i = a; i > b; i--)#define repin(i, a, b) for (int i = a; i <= b; i++)#define depin(i, a, b) for (int i = a; i >= b; i--)#define pi 3.1415926535898#define eps 1e-6#define MOD 1000000007#define MAXN 100100#define N#define Mint m,n;//下面的是用于原图的,即没有SCC之前的图struct Vertex{ ll len,numr;}ver[3*MAXN];int num_ver;struct Edge{ int to,next,from;}edge[10*MAXN];int w,head[3*MAXN];void build_edge(int from,int to){ w++; edge[w].from=from; edge[w].to=to; edge[w].next=head[from]; head[from]=w;}map<string,int>mymap;map<string,int>::iterator it,it1,it2;ll numr;string makelowercasestring(string s){//将string全部转为小写,顺便统计 r 的个数 int len=slen(s); string res; res.clear(); numr=0; rep(i,0,len) { if(isupper(s[i])) s[i]=s[i]-'A'+'a'; res+=s[i]; if(s[i]=='r') numr++; } return res;}void makemap(string s,int t){ mymap.insert(pair<string,int>(s,t));}int pre[3*MAXN],lowlink[3*MAXN],sccbelong[3*MAXN];ll sccnum[3*MAXN];int dfs_clock,scc_cnt;stack<int>st;void tarjan(int now){//缩点,将图变成有向无环图 pre[now]=lowlink[now]=++dfs_clock; st.push(now); int i,to; for(i=head[now];i!=-1;i=edge[i].next) { to=edge[i].to; if(!pre[to]) { tarjan(to); lowlink[now]=min(lowlink[now],lowlink[to]); } else if(!sccbelong[to]) { lowlink[now]=min(lowlink[now],pre[to]); } } if(lowlink[now]==pre[now]) { scc_cnt++; int x; do { x=st.top(); st.pop(); sccbelong[x]=scc_cnt; sccnum[scc_cnt]++; }while(now!=x); }}//下面是用于强联通分量的图,用于新图的struct Vertextarjan{ ll len,numr;}vertarjan[3*MAXN];int num_verr;struct Edgetarjan{ int to,next,from;}edgetarjan[10*MAXN];int headtarjan[3*MAXN],ww;void build_edgetarjan(int from,int to){ ww++; edgetarjan[ww].from=from; edgetarjan[ww].to=to; edgetarjan[ww].next=headtarjan[from]; headtarjan[from]=ww;}bool vis[3*MAXN];void dfs(int now){//dfs搜答案,动态规划处理 vis[now]=true; int i,to; for(i=headtarjan[now];i!=-1;i=edgetarjan[i].next) { to=edgetarjan[i].to; if(!vis[to]) dfs(to); if(vertarjan[now].numr>vertarjan[to].numr) { vertarjan[now].numr=vertarjan[to].numr; vertarjan[now].len=vertarjan[to].len; } else if(vertarjan[now].numr==vertarjan[to].numr && vertarjan[now].len>vertarjan[to].len) { vertarjan[now].len=vertarjan[to].len; } }}string forinput[3*MAXN];//记录输入,统计答案用int main(){ cin>>m; string s; mymap.clear(); num_ver=0; repin(i,1,m) { cin>>s; s=makelowercasestring(s); forinput[i]=s; it=mymap.find(s); if(it!=mymap.end()) continue;//由于以种类为基建图,所以同种类型只让其出现一次 makemap(s,++num_ver); int t=num_ver; ver[t].len=slen(s); ver[t].numr=numr; } cin>>n; string sx,sy; int x,y; w=0; clr_minus1(head); //下面,字符串hash后,以字符串种类为单位建图 repin(ii,1,n) { cin>>sx>>sy; sx=makelowercasestring(sx); it=mymap.find(sx); if(it==mymap.end()) { makemap(sx,++num_ver); int t=num_ver; ver[t].len=slen(sx); ver[t].numr=numr; it=mymap.find(sx); } x=it->second; sy=makelowercasestring(sy); it=mymap.find(sy); if(it==mymap.end()) { makemap(sy,++num_ver); int t=num_ver; ver[t].len=slen(sy); ver[t].numr=numr; it=mymap.find(sy); } y=it->second; build_edge(x,y); } //此时,所有的点和边都适当地建立好了 //下面就开始SCC,将图变成有向无环图 dfs_clock=scc_cnt=0; repin(i,1,num_ver) { if(!pre[i]) tarjan(i); } //下面将tarjan出来的有向无环图建立起来 vector<int>belong[3*MAXN]; //记录每个点属于哪一个强联通分量 repin(i,1,num_ver) { int be=sccbelong[i]; belong[be].pb(i); } ll len=1; num_verr=0; //下面这一步很重要 //将每个强联通分量构建出来,其numr和len值来源于其中的点 //找到其中点numr最小的那个,numr一样找len最小那个,那个点就代表着这个强联通分量,相当于其他点都视为那个最优点 repin(ii,1,scc_cnt) { int len1=gsize(belong[ii]); bool first=true; rep(j,0,len1) { int i=belong[ii][j]; if(first) { first=false; len=ver[i].len; numr=ver[i].numr; continue; } if(ver[i].numr<numr) { numr=ver[i].numr; len=ver[i].len; } else if(ver[i].numr==numr && ver[i].len<len) { len=ver[i].len; } } num_verr++;//ii==num_verr vertarjan[ii].len=len; vertarjan[ii].numr=numr; } //点建好了,根据之前的边的关系找桥,实际上就是找割点,通过桥构建新图的边 //这是将图转换为有向无环图的重要有效方法 clr_minus1(headtarjan); ww=0; int from,to; repin(i,1,w) { from=edge[i].from; to=edge[i].to; if(sccbelong[from]!=sccbelong[to]) { int x1=sccbelong[from],x2=sccbelong[to]; build_edgetarjan(x1,x2); } } //dfs+dp搜 repin(i,1,num_verr) { if(!vis[i]) dfs(i); } //统计答案 ll ans1=0,ans2=0; int be,wh; repin(i,1,m) {//对于输入的这个字符串来说,找到它属于的强联通分量,SCC的答案就是它的答案 //注意建图时候是以种类为基来建图的,但一个种类的字符串可能代表很多个字符串,注意这里 s=forinput[i]; wh=mymap[s]; be=sccbelong[wh]; ans1+=vertarjan[be].numr; ans2+=vertarjan[be].len; } printf("%lld %lld\n",ans1,ans2);}
0 0
- Codeforces 467D. Fedor and Essay (Graphs,dfs,dp,hashing,strings,图论综合型好题)
- codeforces 467D Fedor and Essay dfs
- Codeforces 467D - Fedor and Essay (反向建图 + DFS)
- 【CodeForces】467D Fedor and Essay 强连通+DP
- Codeforces 467D Fedor and Essay bfs
- Codeforces 467D. Fedor and Essay
- Codeforces 467D Fedor and Essay(bfs)
- Codeforces 467D Fedor and Essay(bfs)
- Codeforces Round #267 Div.2 D Fedor and Essay -- 强连通 DFS
- Codeforces Round #267 (Div. 2) D. Fedor and Essay
- Codeforces Round #267 (Div. 2) D. Fedor and Essay
- 有向图强连通分量Tarjan算法+ Codeforces Round #267 (Div. 2) D.Fedor and Essay
- cf 267 div.2 D Fedor and Essay
- Codeforces 682D Alyona and Strings【dp】
- Codeforces 682D Alyona and Strings DP
- Codeforces 754 D Fedor and coupons
- 【codeforces 754D】Fedor and coupons
- codeforces 754D. Fedor and coupons
- ubuntu防火墙关闭命令
- hadoop错误Name node is in safe mode的解决方法
- Hashtable
- first unique character in a string
- Permutation Sequence
- Codeforces 467D. Fedor and Essay (Graphs,dfs,dp,hashing,strings,图论综合型好题)
- 四男子冒充警察抢劫货车杀三人 潜逃十余年终伏法
- Leetcode: Remove Duplicates from Sorted Array I and II
- Text Justification
- <<Python基础教程>>学习笔记 | 第06章 | 抽象
- MAC下用官方方法安装pip
- [摘录] 暴躁程序员的产生
- Leetcode: Longest Palindromic Substring
- 单例模式的七种写法