16:33:56
2020-06-26
当然可以先看一下成绩:
非常显然的成绩不能算有多好,当然其实这也可能是假期水课的报应 (额)
但是比我集训前想象的要好一点(集训时想象的是排名前30就可以,嗯?)
好了,毕竟是第一天,后面日子还长,相信结果不会烂的。
好了,现在看一下第一题:
第一题
原题来自洛谷P2661 :题目链接:https://www.luogu.com.cn/problem/P2661
比较显然的暴力思路(就是我写的)但是复杂度是O(n2)的,显然只有60分。
然后想正解,比较显然想到求一个最小环。但是如何求?
仔细观察这道题可以发现 每人只会把信息告诉一个人,也就是说只有一条出边
然后可以显然的发现图里只有简单环,那么我们可以想到求Tarjan强连通分量。
就是个裸板子,下面是代码:(注意只是这道题比较特殊,才能用Tarjan水过)
#include <cstdio> #include <algorithm> using namespace std; const int maxn=200005; int a[maxn]; int Min=9999999; int dfn[maxn],low[maxn],dfs_clock,sta[maxn],top,belong[maxn],siz[maxn],dcc; void tarjan(int u){ dfn[u]=low[u]=++dfs_clock; sta[++top]=u; int v=a[u]; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); } else if(!belong[v])low[u]=min(low[u],dfn[v]); if(dfn[u]==low[u]){ dcc++; while(1){ int x=sta[top--]; belong[x]=dcc; siz[dcc]++; if(x==u)break; } if(siz[dcc]!=1) Min=min(siz[dcc],Min); } } int main(){ //freopen("a.in","r",stdin); int n;scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=n;i++){ if(!dfn[i])tarjan(i); } printf("%d",Min); return 0; }
但是就这样水过肯定是不行的,那么还有没有其他解法呢?
显然是有的。但是不大好理解,等过会再加。
第二题
这道题当时我是看错题意了,所以想成了树形DP,但成功水了三十分。
其实这道题没有正解,一般人都能想到贪心,但是贪心总是不能AC(80pts)
其实吧,不要想南么复杂,其实数据范围才300 ,直接爆搜(加一小小优化)就能过,
但是代码比较不大好写(本人目前还没有成功写出)
所以代码暂时不给了,先说一下思路:
首先dfs 一遍 求出 deep深度,size 子树大小,和father父亲。
然后依次每一深度枚举切断的边就行了。
代码到时会给的(会加一些注释)。。。。。。