有向图的强连通分量

强联通:两个点之间可以互相到达

如果某个图任意两个点都是强联通的,那么称这个图强联通

如果一个图的子图是强联通的,那么称这个图是强联通子图

一个图的极大强联通子图被称作强连通分量

有强联通分量意味着环

例:受欢迎的牛

如果有环,意味着这个环里的牛都互相喜欢

我们可以先求出环,然后把每一个环都看作一个点,这样整个图就变成了一个DAG(有向无环图)

看有几个点出度为0,如果大于一个点没有出边,就说明没有最受欢迎的牛

如果只有一个,那么强联通分量的大小就是答案

void tarjan(int u){
dfn[u]=++ind;
low[u]=dfn[u];
s[top++]=u;
in[u]=;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(dfn[v]==){//mei bian li dao, v zai zi shu li mian
tarjan(v);
low[u]=min(low[u],low[v]);
}else{//bian li dao le, v bu zai zi shu li mian
if(in[v]){//zai zhan li mian
low[u]=min(low[u],dfn[v]);
}
}
}
if(dfn[u]==low[u]){//fa xian scc
cnt_scc++;
while(s[top]!=u){//bu duan chu zhan
top--;
in[s[top]]=;
scc[s[top]]=cnt_scc;
}
}
}

完整代码:

#include<bits/stdc++.h>
using namespace std; int n,m; int cnt,head[]; struct edge
{
int to,nxt;
}edg[]; inline void add(int from,int to)
{
edg[++cnt].to=to;
edg[cnt].nxt=head[from];
head[from]=cnt;
} int dfn[],low[],ind,in[];
int s[],top;
int cnt_scc;
int scc[],cntscc[]; void tarjan(int x)
{
dfn[x]=++ind;
low[x]=dfn[x];
s[top++]=x;
in[x]=;
for(int i=head[x];i;i=edg[i].nxt)
{
int v=edg[i].to;
if(!dfn[v])
{
tarjan(v);
low[x]=min(low[x],low[v]);
}
else
{
if(in[v])
{
low[x]=min(low[x],dfn[v]);
}
}
}
if(dfn[x]==low[x])
{
cnt_scc++;
while(s[top]!=x)
{
top--;
in[s[top]]=;
scc[s[top]]=cnt_scc;
cntscc[cnt_scc]++;
}
}
} int out[];
int ans; int main()
{
scanf("%d%d",&n,&m);
for(int i=,x,y;i<=m;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
}
for(int i=;i<=n;i++)
{
if(!dfn[i]) tarjan(i);
}
for(int i=;i<=n;i++)
{
for(int j=head[i];j;j=edg[j].nxt)
{
int k=edg[j].to;
if(scc[i]!=scc[k]) out[scc[i]]++;
}
}
for(int i=;i<=cnt_scc;i++)
{
if(!out[i])
{
if(!ans)
ans=i;
else
{
cout<<;
return ;
}
}
}
cout<<cntscc[ans];
}

求强联通分量:

首先想到dfs,我们不妨先看看dfs数

发现有向图中dfs树会有横叉边

显然的事实:一个强连通分量一定是dfs树上的连续的一块

我们定义两个数组

dfn[x]表示x是第几个被dfs到的数(时间戳)

low[x]表示当前节点以及他的子树所有出边所能连到的dfn值中最小的一个

如果某一个点的low和他的dfn相同,就意味着出现强联通分量,就把这个强连通分量拿去(没了)

用一个栈来实现,寻找low时只在栈里面找,弹出时不断从栈顶弹出直到弹出这个点

A gift

把g按照升序排序,枚举g0,跑最小生成树(然后就tle)O(m^2logm)

当我们再连一条新边时,会出现环,所以找到环上的最大的边然后删掉它,复杂度O(n)

总复杂度O(mn)

狼抓兔子

平面图的最小割等于对偶图的最短路

最小割:所有割中边权和最小的割

对偶图:边变成点,点变成边    平面图的每一个块变成一个点,每一条边变成垂直的一条边

#include<cstdio>
#include<cstring>
#define oo 0x3f
#define MAXN 2000001
using namespace std;
struct edge {
int v,to,next;
} e[MAXN*];
int dis[MAXN],q[MAXN],head[MAXN];
bool tag[MAXN];
int n,m,ne,x;
void insert(int u,int v,int w) {
ne++;
e[ne].to=v;
e[ne].next=head[u];
e[ne].v=w;
head[u]=ne;
}
void spfa() {
memset(dis,oo,sizeof(dis));
int t=,w=;
tag[]=;
q[w]=;
dis[]=;
while(t!=w) {
int u=q[t++];
tag[u]=;
if(t==MAXN) t=;
for(int i=head[u]; i; i=e[i].next) {
int v=e[i].to;
if(dis[v]>dis[u]+e[i].v) {
dis[v]=dis[u]+e[i].v;
if(tag[v]==) {
q[w++]=v;
tag[v]=;
if(w==MAXN) w=;
}
}
}
}
}
int main() {
scanf("%d%d",&n,&m);
int nm=(n*m-n-m+)<<;
for(int i=; i<=n; i++) {
for(int j=; j<m; j++) {
scanf("%d",&x);
if(i==) insert(j,nm+,x);
else if(i==n) insert(,(((n-)<<)-)*(m-)+j,x);
else insert(((i-)<<)*(m-)+j,(((i-)<<)-)*(m-)+j,x);
}
}
for(int i=; i<n; i++) {
for(int j=; j<=m; j++) {
scanf("%d",&x);
if(j==) insert(,((i<<)-)*(m-)+,x);
else if(j==m) insert(((i<<)-)*(m-),nm+,x);
else insert(((i-)<<)*(m-)+j-,((i<<)-)*(m-)+j,x);
}
}
for(int i=; i<n; i++) {
for(int j=; j<m; j++) {
scanf("%d",&x);
insert((((i-)<<)+)*(m-)+j,((i-)<<)*(m-)+j,x);
}
}
spfa();
printf("%d\n",dis[nm+]);
return ;
}

奶牛的旅行

0/1分数规划

二分答案+spfa判负环

最优比率生成树

抢掠计划

把强联通分量缩点

从点1开始跑一遍最长路spfa,在酒吧取max

奶牛接力跑

倍增floyd(floyd快速幂)

g[1][i][j]表示从i到j只经过一条边的最短路

如何转移到g[2][i][j]?

枚 举所有中点k,对于所有的k,g[2][i][j]表示min(g[1][i][k]+g[1][k][j])

同理也可以求出g[4][i][k]

所以g[p][i][j]=min(g[p/2][i][k]+g[p/2][k][j])

g[3][i][j]=min(g[2][i][k]+g[1][k][j])

和快速幂的关系:用类似于快速幂的方法将其分解

while(b){
if(b&){
memset(f,0x3f,sizeof(f));
for(int k=;k<=n;k++){
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
f[i][j]=min(f[i][j],ret[i][k]+g[k][j]);
}
}
}
memcpy(ret,f,sizeof(f));
}
memset(f,0x3f,sizeof(f));
for(int k=;k<=n;k++){
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
f[i][j]=min(f[i][j],g[i][k]+g[k][j]);
}
}
}
memcpy(g,f,sizeof(f));
   b>>=1;
} print(ret[S][E])

Destroying road

  1. 两条最短路不交叉  删掉的边的数量:m-dis[s1][t1]-dis[s1][t2]
  2. 两条最短路有公共部分

Bfs求最短路

匈牙利算法:配对

int g[N][N];
int lk[N];// mei zi xi huan na ge nan de
bool vis[N];//zhe yi lun, mei zi you mei you bei jiao huan bool find(int x){
for(int i=;i<=n;i++){
if(!vis[i]&&g[x][i]){
vis[i]=;
if(lk[i]==||find(lk[i])){
lk[i]=x;
return ;
}
}
}
return ;
} for(int i=;i<=n;i++){
memset(vis,,sizeof(vis));
if(find(i)){
hunpei++;
}else{
break;
}
}

差分约束系统

最小化最长路

例题:糖果

qbzt day4 下午的更多相关文章

  1. Day4下午解题报告

    预计分数:30+30+0=60 实际分数:30+30+10=70 稳有个毛线用,,又拿不出成绩来,, T1 https://www.luogu.org/problem/show?pid=T15626 ...

  2. Day4下午

    不会啊. T1 找规律: 辗转相减,加速. #include<iostream> #include<cstring> #include<cstdio> #inclu ...

  3. qbzt day6 下午 模拟赛

    我太菜了 T2 给定一张有向图,每个点有点权.试找到一条路径,使得该路径上的点权最 大值减去点权最小值最大,问这个差最大是多少.   话说这个题第一个想到的思路是tarjan缩点+拓扑排序来着... ...

  4. qbzt day5 下午

    农场主John新买了一块长方形的新牧场,这块牧场被划分成M行N列(1 ≤ M ≤ 12; 1 ≤ N ≤ 12),每一格都是一块正方形的土地.John打算在牧场上的某几格里种上美味的草,供他的奶牛们享 ...

  5. qbzt day4 上午

    图论 最短路:dijkstra   spfa   floyd 最小生成树:kruskal 连通性:bfs/dfs    tarjan(强连通分量) 其它:拓扑排序    LCA 齿轮: 图的dfs树只 ...

  6. qbzt day3 下午(好难)

    内容提要 有关数据结构的例题 求逆序对数 统计每个数前面有多少比他大的数 开数组表示这个数之前0~9这些数出现了几次 动态将某个点加一,动态求前缀和 用树状数组 如果数太大了怎么办? 离散化 步骤:先 ...

  7. qbzt day2 下午

    内容提要 高精 矩阵 筛法 先是高精除法 注意细节 高精度开方:神奇的竖式 以小数点为分界线,每两个位砍一刀 87654.321-->08|76|54|.32|1 大概就是先对第一位开方,然后相 ...

  8. WC2017 游记

    你若安好,便是晴天. 其实本来是有一个写的比较详细的游记的……然而后来给断了,懒得补上了,简单一点好了. Day 0 早早爬起来去赶高铁…… 路上没太多可以写的……坐高铁的时候想起来了一些不开心的事情 ...

  9. Alpha冲刺! Day4 - 磨刀

    Alpha冲刺! Day4 - 磨刀 今日已完成 晨瑶:和大家交流了一下,反思这阶段团队遇到的问题. 昭锡:今天跟学长交流了点问题,学习了Gson使用. 永盛:Gravel 数据库重新设计. 立强:看 ...

随机推荐

  1. css是干什么的

    css这些长篇累牍的参数,其实就是这些所谓的css编程者每天要干的事情了,他们把这些参数熟记于心,就像c++程序员,把这些函数库熟记于心一样,都是编程. css定制了每一个单独的组件,这些组件要么是相 ...

  2. 打印Java main参数

    public class Main { public static void main(String args[]){ System.out.println("打印main方法中的输入参数, ...

  3. Hive常用数据库操作

    1.创建表的三种姿势 第一种 //员工表 create table if not exists default.emp( empno int, ename string, job string, mg ...

  4. linux 打包和压缩的概念和区别

    对于刚刚接触Linux的人来说,一定会给Linux下一大堆各式各样的文件名 给搞晕.别个不说,单单就压缩文件为例,我们知道在Windows下最常见的压缩文件就只有两种,一是,zip,另一个是.rar. ...

  5. Codeforces 955 LR询问 多次幂处理

    A 模拟题 #include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) ...

  6. 1121. Damn Single (25)

    "Damn Single (单身狗)" is the Chinese nickname for someone who is being single. You are suppo ...

  7. qt03 QString和QByteArray相互转换

    QString str("hello");   QByteArray bytes = str.toUtf8(); // QString转QByteArray方法1       QS ...

  8. 【学习】014 深入理解Http协议

    Http协议入门 什么是http协议 http协议: 对浏览器客户端 和  服务器端 之间数据传输的格式规范 查看http协议的工具 1)使用火狐的firebug插件(右键->firebug-& ...

  9. Comet OJ - 模拟赛 #2 Day1 比赛总结

    比赛情况 40 + 60 + 0 = 100pts 哎,T1做错了,没有对拍.如果发现错误 \(=>\) 改正 \(=>\) 40->100pts,160pts \(=>\) ...

  10. springboot+HttpInvoke 实现RPC调用

    开始用springboot2+hession4实现RPC服务时,发现第一个服务可以调用成功,但第二个就一直报 '<' is an unknown code.第一个服务还是可以调用的.参考网上的方 ...