题意:给出一个有向图,最多添加多少条边使这个图依然不是强连通图;当这个图是强连通图时,输出-1;

求解思路:强连通分量求解:
强连通图:在有向图中,任意节点除法都可以到达其余所有节点,则称为强连通图。
强连通分量:在非强连通图的有向图中,选取部分点为强连通图,该强连通子图称为强连通分量

方法一:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<stack>
using namespace std;
const int maxx=50005;
const int inf=0x3f3f3f3f;
vector<int>Map[maxx];
int vis[maxx];
int n,m;
int indegree[maxx];
int outdegree[maxx];
int dfn[maxx];
int low[maxx];
int flag[maxx];
int sum[maxx];
int ans;
int k;
struct node{int v,u;int cost;node(){}node(int v,int cost):v(v),cost(cost){}
};
vector<node>e[maxx];
stack<int>s;
int index;
void init(){index=0;ans=0;memset(sum,0,sizeof(sum));memset(indegree,0,sizeof(indegree));memset(outdegree,0,sizeof(outdegree));memset(vis,0,sizeof(vis));memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(flag,0,sizeof(flag));for(int i=0;i<=n;i++){Map[i].clear();e[i].clear();}
}
void dfs(int u){index++;low[u]=dfn[u]=index;s.push(u);vis[u]=1;for(int i=0;i<Map[u].size();i++){int v=Map[u][i];if(dfn[v]==0){dfs(v);low[u]=min(low[u],low[v]);}else if(vis[v]==1){low[u]=min(low[u],dfn[v]);}}if(dfn[u]==low[u]){int v;ans++;do{v=s.top();s.pop();vis[v]=0;flag[v]=ans;sum[ans]++;}while(u!=v);}
}
int main(){int count=1;int t;scanf("%d",&t);while(t--){scanf("%d %d",&n,&m);init();for(int i=1;i<=m;i++){int a,b;scanf("%d %d",&a,&b);Map[a].push_back(b);}for(int i=1;i<=n;i++){if(dfn[i]==0){dfs(i);}}for(int i=1;i<=n;i++){for(int j=0;j<Map[i].size();j++){int t=Map[i][j];if(flag[t]!=flag[i]){outdegree[flag[i]]++;indegree[flag[t]]++;}}}int ans1=0,ans2=0;for(int i=1;i<=ans;i++){if(outdegree[i]==0||indegree[i]==0){ans1=sum[i];ans2=max(ans2,ans1*(ans1-1)+(n-ans1)*(n-ans1-1)+ans1*(n-ans1)-m);}}cout<<"Case "<<count++<<": ";if(ans==1){cout<<-1<<endl;}else{cout<<ans2<<endl;}}return 0;
}

Kosaraju算法:
算法思路:
步骤1:对正向图(原图)进行dfs求解得到正向图中各节点的拓扑序并且存在数组vs中。
步骤2:得到拓扑序之后,对反向图按照逆拓扑序进行rdfs,每次rdfs都得到一个强连通分量。
注意:在进行第一步的dfs之后,将数组vis清空。

注解:Map数组记录正向图,rMap数组记录反向图,flag数组标记属于哪个连通分量,vis数组标记访问情况,vs数组记录拓扑序。

方法二:Kosaraju算法
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
const int maxx=50005;
const int inf=0x3f3f3f3f;
vector<int>Map[maxx],rMap[maxx],vs;
int vis[maxx];
int n,m;
int flag[maxx];
int sum[maxx];
int indegree[maxx];
int outdegree[maxx];
int ans;
struct node{int v,u;int cost;node(){}node(int v,int cost):v(v),cost(cost){}
};
vector<node>e[maxx];
void init(){ans=0;memset(sum,0,sizeof(sum));memset(indegree,0,sizeof(indegree));memset(outdegree,0,sizeof(outdegree));memset(vis,0,sizeof(vis));memset(flag,0,sizeof(flag));for(int i=0;i<=n;i++){rMap[i].clear();Map[i].clear();}vs.clear();
}
void dfs(int v){vis[v]=1;for(int i=0;i<Map[v].size();i++){int t=Map[v][i];if(vis[t]==0){dfs(t);}}vs.push_back(v);
}
void rdfs(int v,int k){vis[v]=1;flag[v]=k;//v代表属于k这个连通分量 sum[k]++;for(int i=0;i<rMap[v].size();i++){int t=rMap[v][i];if(vis[t]==0){rdfs(t,k);}}
}
void solve(){for(int i=1;i<=n;i++){if(vis[i]==0){dfs(i);}}memset(vis,0,sizeof(vis));for(int i=vs.size()-1;i>=0;i--){if(vis[vs[i]]==0){ans++;rdfs(vs[i],ans);}}
}
int main(){int count=1;int t;scanf("%d",&t);while(t--){scanf("%d %d",&n,&m);init();for(int i=1;i<=m;i++){int a,b;scanf("%d %d",&a,&b);Map[a].push_back(b);rMap[b].push_back(a);}solve();for(int i=1;i<=n;i++){for(int j=0;j<Map[i].size();j++){int t=Map[i][j];if(flag[t]!=flag[i]){outdegree[flag[i]]++;indegree[flag[t]]++;}}}int ans1=0,ans2=0;for(int i=1;i<=ans;i++){if(outdegree[i]==0||indegree[i]==0){ans1=sum[i];ans2=max(ans2,ans1*(ans1-1)+(n-ans1)*(n-ans1-1)+ans1*(n-ans1)-m);}}cout<<"Case "<<count++<<": ";if(ans==1){cout<<-1<<endl;}else{cout<<ans2<<endl;}}return 0;
} 

HDU4635(强连通分量+Kosaraju算法)相关推荐

  1. HDU2767(强连通分量+Kosaraju算法)

    题意:需要加多少边才能把一个图变成强连通分量 强连通图:在有向图中,任意节点除法都可以到达其余所有节点,则称为强连通图. 强连通分量:在非强连通图的有向图中,选取部分点为强连通图,该强连通子图称为强连 ...

  2. 打印有向图的强连通分量-----kosaraju算法(最简单的实现)

    一.kosaraju算法步骤: 1.首先对图G进行一次DFS,记录每个顶点完成的顺序(DFS树/林的叶子节点先完成,然后回溯到它双亲这一层,它个双亲递归遍历完自己的邻居并在这些递归完成回溯到这层后,它 ...

  3. 有向图强连通分量tarjan算法

    转自:http://www.byvoid.com/blog/scc-tarjan/ http://blog.csdn.net/geniusluzh/article/details/6601514 在有 ...

  4. 强连通分量 Kosaraju PK Tarjan(转)

    转自scameeling的空间 http://hi.baidu.com/scameeling/item/b135831094ec756771d5e815 强连通分量 Kosaraju PK Tarja ...

  5. 强连通分量(Tarjan算法)和缩点

    强连通分量(Tarjan算法)和缩点 一些定义 给定一张有向图,对于图中任意两个节点 xxx 和 yyy ,存在从 xxx 到 yyy 的路径,也存在从 yyy 到 xxx 的路径,则称该有向图为强连 ...

  6. 强连通分量(Tarjan算法) 图解

    强连通分量(Tarjan算法) 前言 第一件事:没事不要while(m–),会带来不幸 第二件事:看博客先看看评论,如果博主他写错了的话- 简介 先讲几个定义 强连通:两个顶点 uuu,vvv 可以相 ...

  7. 图之强连通、强连通图、强连通分量 Tarjan算法

    一.解释 在有向图G中,如果两个顶点间至少存在一条互相可达路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大强 ...

  8. 有向图的强连通分量--Tarjan算法---代码分析

    本文就是做个代码分析,顺便说下理解. 一.预备知识: 需要知道什么是: 回边.前向边.交叉边 二.上代码: #include<algorithm> #define NIL -1using ...

  9. 强连通分量——tarjan算法缩点

    一. 什么是强连通分量? 强连通分量:在有向图G中,如果两个顶点u,v间(u->v)有一条从u到v的有向路径,同时还有一条从v到u的有向路径,则称两个顶点强连通(strongly connect ...

最新文章

  1. python close函数_Matplotlib的close()函数使Tkinter GUI窗口关闭
  2. 邮箱@topgrid.cn是什么网站_典 藏 网 站 !
  3. mybatis教程--一对多查询
  4. MYSQL5.7版本sql_mode=only_full_group_by问题
  5. 电脑数据存储工具----光盘驱动器
  6. 押中三位奥运冠军 元气森林“赢麻了”
  7. python保存列表到json_将json数据保存到python列表中时出现问题
  8. Solr管理索引库——(十三)
  9. SylixOS arm64 异常向量表
  10. 2019软件设计师考试要点
  11. LM75温度传感器数据采集实验
  12. 计算机网络-IP协议
  13. web前端 vue axios 网页设计
  14. PyTorch入门: Kaggle 泰坦尼克幸存者预测
  15. win10找不到wifi网络_当WiFi和4G网络齐飞,你的手机恐怕撑不到回家充电了…
  16. Python黑科技:暴力破解你的密码
  17. 用Python自动识别验证码(完整教程,陆续更新12306验证码识别,抢票)
  18. Proteus安装后点击“ISIS 7 professional”报错:cannot find a valid licence key for ISIS Professional on this co
  19. CC2640R2F学习笔记(四.电源管理:用电源管理开发应用程序)
  20. “深圳首届十大金口碑人物”优必选科技创始人兼CEO周剑获此殊荣

热门文章

  1. html 的基本结构、标签(分类、关系)、文档类型、页面语言、字符集、语义化
  2. python中json的使用
  3. JSP第二次作业_4小题
  4. C语言,二维数组的逗号!_只愿与一人十指紧扣_新浪博客
  5. 熬了几个大夜,学完一套985博士总结的OpenCV学习笔记(20G高清/PPT/代码)
  6. 深度学习中的反向卷积
  7. Car-eye-http-flv-module 实现nginx-rtmp-mudule HTTP方式的FLV直播功能
  8. Angular5学习笔记 - 虚拟RestfulApi配置与使用(六)
  9. SpringCloud(第 051 篇)EurekaServer集群高可用注册中心以及简单的安全认证
  10. 《Android App开发入门:使用Android Studio 2.X开发环境》——1-3 Android Studio 快速上手...