• P3387 【模板】缩点
  • P3388 【模板】割点(割顶)
  • P2341 [USACO03FALL][HAOI2006]受欢迎的牛 G
  • P2863 [USACO06JAN]The Cow Prom S
  • P2746 [USACO5.3]校园网Network of Schools
  • P1407 [国家集训队]稳定婚姻
  • P2272 [ZJOI2007]最大半连通子图
  • P3225 [HNOI2012]矿场搭建
  • P5058 [ZJOI2004]嗅探器
  • P2515 [HAOI2010]软件安装

1.P3387 【模板】缩点

缩点后topo排序dp

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5,maxm=1e5+5;
int n,m;
int dq[maxn],ru[maxn],dis[maxn],a[maxm],b[maxm];
int dfn[maxn],low[maxn],vis[maxn],z[maxn],color[maxn],cnt[maxn],du[maxn],t,k,tot;vector<int>e[maxm];
vector<int>g[maxm];
void tarjan(int u){dfn[u]=low[u]=++tot;z[++k]=u;//入栈 vis[u]=1;for(int i=0;i<e[u].size();i++){if(!dfn[e[u][i]]){tarjan(e[u][i]);low[u]=min(low[u],low[e[u][i]]);}else if(vis[e[u][i]]){low[u]=min(low[u],dfn[e[u][i]]);}}if(low[u]==dfn[u]){int y;while(y=z[k--]){color[y]=u;    //属于这个连通分量 cnt[t]++;         //记录这个环中有多少个点vis[y]=0;if(u==y)break;dq[u]+=dq[y];}}
}
int topo(){queue<int>q;for(int i=1;i<=n;i++){if(color[i]==i&&!ru[i]){q.push(i);dis[i]=dq[i];}}while(!q.empty()){int u=q.front();q.pop();for(int i=0;i<g[u].size();i++){int v=g[u][i]; ru[v]--;dis[v]=max(dis[v],dis[u]+dq[v]);if(ru[v]==0){q.push(v);}}}int res=0;for(int i=1;i<=n;i++){res=max(res,dis[i]);}return res;
}
int main(){cin>>n>>m;for(int i=1;i<=n;i++){scanf("%d",&dq[i]);}for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);e[u].push_back(v);a[i]=u;b[i]=v;}for(int i=1;i<=n;i++){if(!dfn[i])tarjan(i);}for(int i=1;i<=m;i++){int x=color[a[i]],y=color[b[i]];if(x!=y){g[x].push_back(y);ru[y]++;}}cout<<topo();return 0;
}

2.P3388 【模板】割点(割顶)

3.P2341 [USACO03FALL][HAOI2006]受欢迎的牛 G

缩点+割点模板

4.P2863 [USACO06JAN]The Cow Prom S

纯模板

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5,maxm=1e5+5;
int n,m;
int dfn[maxn],low[maxn],vis[maxn],z[maxn],color[maxn],cnt[maxn],du[maxn],t,k,tot;
vector<int>e[maxm];
void tarjan(int u){dfn[u]=low[u]=++tot;z[++k]=u;//入栈 vis[u]=1;for(int i=0;i<e[u].size();i++){if(!dfn[e[u][i]]){tarjan(e[u][i]);low[u]=min(low[u],low[e[u][i]]);}else if(vis[e[u][i]]){low[u]=min(low[u],dfn[e[u][i]]);}}if(low[u]==dfn[u]){t++;//连通分量的标号 do{color[z[k]]=t;    //属于这个连通分量 cnt[t]++;         //记录这个环中有多少个点vis[z[k]]=0; k--;              //出栈 }while(u!=z[k+1]);}
}
int main(){cin>>n>>m;for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);e[u].push_back(v);}for(int i=1;i<=n;i++){if(!dfn[i])tarjan(i);}for(int i=1;i<=n;i++){for(int j=0;j<e[i].size();j++){if(color[i]!=color[e[i][j]])du[color[i]]++;}}int ans=0;for(int i=1;i<=t;i++){if(cnt[i]>1)ans++;}cout<<ans;return 0;
}

5.P2746 [USACO5.3]校园网Network of Schools

kuangbin联通性专题t1

6.P1407 [国家集训队]稳定婚姻

题目给出的夫妻和情侣都是双向边的该怎么办呢
一个很棒的思路:一种 男->女 连边,另外一一种 女->男 连边
然后缩点,如果在这对情侣在同一个强联通分量里面的话就有问题

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+5,maxm=5e4+5;
unordered_map<string,int>mp;
int dfn[maxn],low[maxn],vis[maxn],z[maxn],color[maxn],cnt[maxn],t,k,tot;
int n,m;
vector<int>e[maxm];
string mb[maxn],mg[maxn];
void tarjan(int u){dfn[u]=low[u]=++tot;z[++k]=u;vis[u]=1;for(int i=0;i<e[u].size();i++){int v=e[u][i];if(!dfn[v]){tarjan(v);low[u]=min(low[u],low[v]);}else if(vis[v]){low[u]=min(low[u],dfn[v]);}}if(low[u]==dfn[u]){t++;do{color[z[k]]=t;cnt[t]++;vis[z[k]]=0;k--;}while(u!=z[k+1]);}
}
int main(){cin>>n;int cx=0;string s1,s2;for(int i=1;i<=n;i++){cin>>s1>>s2;mp[s1]=i;mp[s2]=i+n;e[i].push_back(i+n);}cin>>m;for(int i=1;i<=m;i++){cin>>s1>>s2;e[mp[s2]].push_back(mp[s1]);}for(int i=1;i<=n*2;i++){if(!dfn[i])tarjan(i);}for(int i=1;i<=n;i++){if(color[i]==color[i+n]){printf("Unsafe\n");}else printf("Safe\n");}return 0;
}

7.P2272 [ZJOI2007]最大半连通子图

这个题的题意硬是看了半天都没有看懂
如果有u到v的一条边的话称u和v为半联通,求最大的半联通子图
既然有有一条边就是半联通的话,那缩点自然也是半联通
先缩点
然后DAG上DP
因为tarjan缩点完自带逆拓扑序,所以直接倒着遍历就是拓扑序

dp时的转移:

            if(ans[v]<ans[u]+cnt[v]){ans[v]=ans[u]+cnt[v];tiao[v]=tiao[u];}else if(ans[v]==ans[u]+cnt[v]){tiao[v]+=tiao[u];tiao[v]%=mod;}

完整代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5,maxm=4e6+5;
int dfn[maxn],low[maxn],vis[maxn],z[maxn],color[maxn],cnt[maxn],t,k,tot;
int n,m,mod,ans[maxn],use[maxn],tiao[maxn];
vector<int>e[maxm];
int head[maxn];
struct edge{int v,nex;
}ee[maxm];
int bs;
void add(int u,int v){ee[++bs].v=v;ee[bs].nex=head[u];head[u]=bs;
}
void tarjan(int u){dfn[u]=low[u]=++tot;z[++k]=u;vis[u]=1;for(int i=0;i<e[u].size();i++){int v=e[u][i];if(!dfn[v]){tarjan(v);low[u]=min(low[u],low[v]);}else if(vis[v]){low[u]=min(low[u],dfn[v]);}}if(low[u]==dfn[u]){t++;do{color[z[k]]=t;cnt[t]++;vis[z[k]]=0;k--;}while(u!=z[k+1]);}
}
int main(){cin>>n>>m>>mod;int u,v;for(int i=1;i<=m;i++){scanf("%d%d",&u,&v);e[u].push_back(v);}for(int i=1;i<=n;i++){if(!dfn[i])tarjan(i);}for(int u=1;u<=n;u++){ans[u]=cnt[u];tiao[u]=1;for(int i=0;i<e[u].size();i++){int v=e[u][i];if(color[u]==color[v])continue;add(color[u],color[v]);}}for(int u=t;u>=1;u--){for(int i=head[u];i;i=ee[i].nex){int v=ee[i].v;if(use[v]==u)continue;use[v]=u;if(ans[v]<ans[u]+cnt[v]){ans[v]=ans[u]+cnt[v];tiao[v]=tiao[u];}else if(ans[v]==ans[u]+cnt[v]){tiao[v]+=tiao[u];tiao[v]%=mod;}}}int mm=0;int tt=0;for(int i=1;i<=t;i++){if(mm<ans[i]){mm=ans[i];tt=tiao[i];}else if(mm==ans[i]){tt+=tiao[i];tt%=mod;}}cout<<mm<<endl<<tt;return 0;
}

8.P3225 [HNOI2012]矿场搭建

这题需要分情况讨论
样例1:

可以看出点1是割点,然后我们分析样例的答案:
Case 1 的四组解分别是(2,4),(3,4),(4,5),(4,6);
割点两边各取一个点

样例2:

图中1 2 3是割点,取法唯一
Case 2 的一组解为(4,5,6,7)。

样例3:

割点是4 6 10
来分析一下怎么样统计需要多少个救援点和有多少种安排法

当一个联通块里没有割点时候,例如一个环,只要安排两个救援点,这时候不管切断哪个点,其他点都能继续连通,方案数为Cn2\mathrm{C}_n^2Cn2​

    if(c==0){gs+=2;ans*=(ds-1)*ds/2;}

当一个联通块里有一个割点,比如样例一:1 ,2,3,5,6这个联通块,就需要在里面选一个非割点的点作为救援点

    if(c==1){gs+=1;ans*=ds;}

当一个联通块里有两个或者两个以上的割点,如样例3的4,5,6这个联通块,并不需要做任何处理,因为这两个以上个割点,在其他联通块已经把救援点处理好了,不管断哪个点都能互相联通

还有一个坑点就是一开始并没有给出点的数量,需要自己在输入过程中维护
还有%lld 惨痛RE
完整代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e5+5,maxm=4e5+5;
int dfn[maxn],low[maxn],vis[maxn],t,top,tot;
int cut[maxn],n,m,head[maxn],len;
struct edge{int v,nex;
}e[maxm];
inline void add(int u,int v){e[++len].v=v;e[len].nex=head[u];head[u]=len;
}
void tarjan(int u,int root){int child=0;dfn[u]=low[u]=++tot;for(int i=head[u];i;i=e[i].nex){int v=e[i].v;if(!dfn[v]){tarjan(v,root);low[u]=min(low[u],low[v]);if(low[v]>=dfn[u]&&u!=root)cut[u]=1;if(u==root)child++;}low[u]=min(low[u],dfn[v]);}if(u==root&&child>=2){cut[root]=1;}
}
int c,ds,color;
void dfs(int u){ds++;vis[u]=color;for(int i=head[u];i;i=e[i].nex){int v=e[i].v;if(cut[v]&&vis[v]!=color){vis[v]=color;c++;}if(vis[v]==0)dfs(v);}return;
}
void init(){memset(head,0,sizeof head);memset(dfn,0,sizeof dfn);memset(cut,0,sizeof cut);memset(vis,0,sizeof vis);memset(low,0,sizeof low);color=0;len=0,t=0,top=0,tot=0;
}
signed main(){int tt=1;while(scanf("%lld",&n),n){init();int zdd=0;long long ans=1;long long gs=0;int u,v;for(int i=1;i<=n;i++){scanf("%lld%lld",&u,&v);add(u,v);add(v,u);zdd=max(zdd,u);zdd=max(zdd,v);}for(int i=1;i<=zdd;i++){if(!dfn[i])tarjan(i,i);}for(int i=1;i<=zdd;i++){if(vis[i]==0&&cut[i]==0){ds=0;c=0;color++;dfs(i);if(c==1){gs+=1;ans*=ds;}if(c==0){gs+=2;ans*=(ds-1)*ds/2;}}}printf("Case %lld: %lld %lld\n",tt++,gs,ans);}return 0;
}

9.P5058 [ZJOI2004]嗅探器

这个题其实比较套路
读懂题之后发现是要找到一个割点,让st和ed在两边,且编号最小
要怎么实现st和ed在两边呢?
直接拿st建树来求割点,找到割点后,判断ed的dfn是否大于等于割点u所连点v,如果符合,st和ed就必定是在割点的两边,直接在tarjan的过程中特判一下就好

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5,maxm=1e6+5;
int dfn[maxn],low[maxn],vis[maxn],z[maxn],color[maxn],cnt[maxn],t,top,tot;
int cut[maxn],n,m,head[maxn],len,st,ed;
struct edge{int v,nex;
}e[maxm];
inline void add(int u,int v){e[++len].v=v;e[len].nex=head[u];head[u]=len;
}
void tarjan(int u,int root){int child=0;dfn[u]=low[u]=++tot;z[++top]=u;for(int i=head[u];i;i=e[i].nex){int v=e[i].v;if(!dfn[v]){tarjan(v,root);low[u]=min(low[u],low[v]);if(low[v]>=dfn[u]&&u!=root&&dfn[ed]>=dfn[v])cut[u]=1;if(u==root)child++;}low[u]=min(low[u],dfn[v]);}if(u==root&&child>=2){cut[root]=1;}
}
int main(){cin>>n;int u,v;while(scanf("%d%d",&u,&v),u+v){add(u,v);add(v,u);}scanf("%d%d",&st,&ed);tarjan(st,st);for(int i=1;i<=n;i++){if(cut[i]&&i!=st){cout<<i;return 0;}}printf("No solution");return 0;
}

10.P2515 [HAOI2010]软件安装

树形DP还没学会,先咕咕咕

能力提升综合题单 Part 8.7 图的连通性相关相关推荐

  1. 洛谷 能力提升综合题单Part1 入门阶段 P1089 津津的储蓄计划 带注释

    题目描述 津津的零花钱一直都是自己管理.每个月的月初妈妈给津津300300元钱,津津会预算这个月的花销,并且总能做到实际花销和预算的相同. 为了让津津学习如何储蓄,妈妈提出,津津可以随时把整百的钱存在 ...

  2. 教师计算机校本培训心得,小学教师信息技术应用能力提升工程网络与校本研修心得体会...

    小学教师信息技术应用能力提升工程网络与校本研修心得体会 通过参加厦门市同安区中小学教师信息技术应用能力提升工程网络与校本研修,我收获颇丰,总结几点如下: 首先,通过认真倾听各位专家视频讲座,全面感受信 ...

  3. 清华大学大数据能力提升项目开始报名啦 !(2019年秋季)

    数据院定于2019年8月28日晚19:00-21:00在明理楼112召开"大数据教育在清华"暨清华大学大数据能力提升项目招生宣讲会,欢迎同学们前来参与!  项目定位 在全球大数据浪 ...

  4. 蔡丹红老师刁酒集团《基层管理人员综合能力提升培训班》企业内训开讲

    蔡丹红老师:刁酒集团<基层管理人员综合能力提升培训班>企业内训开讲 一线员工总是奋斗在前线,为公司打开销路.打开渠道,为公司创造业绩,作为基层管理人员应做好本职工作,努力提升自己,提高综合 ...

  5. 软件技术专业大学生该如何制定职业综合能力提升计划

    记得那还是五年级的时候,那时班主任叫我们写上自己的理想吧.我就记得自己写了成为一个对社会有用的人,而别的同学都写上科学家和老师等等.但随着不断的成长,我们都走上了自己特定的人生轨道.这个时候我们不能再 ...

  6. 《大数据实践课》开创实践教学新模式:清华大数据能力提升项目特色课程系列报道之一

    2014年4月,清华大学顺应时代潮流成为全国第一批成立大数据研究机构的高等学府.四年来,清华-青岛数据科学研究院(以下简称:数据院)与研究生院共同设计组织实施了以大数据能力提升项目为主的大数据人才培养 ...

  7. 计算机网络技术综合题大全

    第1章 计算机网络概述 一.简答题 1.简述计算机网络的发展过程. 答:从1946年世界上第一台计算机ENIAC的诞生到现在网络的全面普及,计算机网络的发展大体可以分为以下4个阶段: (1)第一代计算 ...

  8. 教师计算机培训重要性日志,2018教师信息技术应用能力提升专题培训研修日志...

    <2018教师信息技术应用能力提升专题培训研修日志>由会员分享,可在线阅读,更多相关<2018教师信息技术应用能力提升专题培训研修日志(3页珍藏版)>请在人人文库网上搜索. 1 ...

  9. 计算机教学能力提升体会,教师信息技术能力提升学习心得

    教师信息技术能力提升学习心得 发布时间:2019-09-17 导语:当今以计算机和网络技术为核心的现代技术正飞速的发展,改变我们的学习方式,信息的获取.分析.处理.应用的能力将作为现代人最基本的能力和 ...

  10. 继续教育研修计算机总结与反思,教师信息技术能力提升研修反思日志

    教师信息技术能力提升研修反思日志 随着信息技术的不断发展,多媒体教学.信息技术平台等成为活跃课堂.调动学生学习积极性的一种主要手段."国培计划"为提高教师的自身水平提供了良好的平台 ...

最新文章

  1. 锐捷路由器--多线路应用路由
  2. 计算机用户停用无法登录,电脑开机无法登录提示您的账户已被停用如何解决。 如何解决电脑开机无法登录提示您的账户已被停用的问题。...
  3. redis最基础的入门教程
  4. dev控件调用html页面,Chrome开发工具 扩展 DevTools
  5. 剑指offer之链表中倒数第K个节点
  6. 怎么估算空间利用率?新研发传感器分分钟搞定!
  7. 两个HC05蓝牙模块相互之间的通信
  8. 成手指状态html,css手势状态定义属性cursor和自定义鼠标手势详解
  9. iredmail邮件服务器安装流程
  10. Android各版本号及其英文别名
  11. echarts三维建筑地图注解
  12. 微信小程序中使用wx.showToast()进行界面交互
  13. 【一句日历】2019年8月
  14. Java多线程系列--“JUC锁”04之 公平锁(二)
  15. 大家的人工智能——学习路线总览
  16. Java整合Jsonpath解析Json字符串
  17. 浏览器标签中显示京东logo
  18. 遗传算法(二)——编码
  19. Linova and Kingdom
  20. 国外服务器和国内服务器 不同时区的问题

热门文章

  1. 一眼把人看穿之社交方式 如何辨别朋友的信任度
  2. 查找数组中特定元素_Leetcode 540 题 有序数组中的单一元素
  3. Java 基于UDP 实现单播、组播、广播 Socket 编程
  4. Java求矩形面积和圆形面积的异常处理实例
  5. linux下client命令,Linux系统smbclient命令的使用方法
  6. cad新手必练300图_CAD建筑图纸看不懂?最简单识图方法都在这,收藏记得看
  7. c语言中宏名的作用时段,C语言中的宏定义!
  8. Linux内核分析:跟踪分析Linux内核的启动过程
  9. mysql5.5.53安装教程_mysql5.5.28安装教程 超详细!
  10. android 关掉屏幕旋转,防止在Android中屏幕旋转时解除对话框