题干:

Give a simple directed graph with N nodes and M edges. Please tell me the maximum number of the edges you can add that the graph is still a simple directed graph. Also, after you add these edges, this graph must NOT be strongly connected. 
A simple directed graph is a directed graph having no multiple edges or graph loops.
A strongly connected digraph is a directed graph in which it is possible to reach any node starting from any other node by traversing edges in the direction(s) in which they point. 

Input

The first line of date is an integer T, which is the number of the text cases. 
Then T cases follow, each case starts of two numbers N and M, 1<=N<=100000, 1<=M<=100000, representing the number of nodes and the number of edges, then M lines follow. Each line contains two integers x and y, means that there is a edge from x to y.

Output

For each case, you should output the maximum number of the edges you can add. 
If the original graph is strongly connected, just output -1.

Sample Input

3
3 3
1 2
2 3
3 1
3 3
1 2
2 3
1 3
6 6
1 2
2 3
3 1
4 5
5 6
6 4

Sample Output

Case 1: -1
Case 2: 1
Case 3: 15

解题报告:

这题首先缩点,因为这些点之间肯定是强连通的,我们为了不让他是个强连通图,就是要新图不再是一个强连通分量就可以了。Tarjan处理完了之后得到每个集合的点数和一张新图,我们不去建图,只需要记录入度和出度,这样就得到了一张DAG图。我们要想加的边尽量多但是不让他是一个强连通图,那么就需要让这个新图的scc控制在2。也就是刚刚好不是个强连通,所以我们先假设连上了所有的边,然后考虑哪些边是不能加的。特就是将新图分成两个大集合,让他们之间只有单向边就可以了。也就是我们要找到一个大集合A和大集合B,元素个数假设分别为x和n-x,这样要减去的边数就是x*(n-x),要让这个值尽量小,所以我们枚举每一个小集合(要出度为0或者入度为0的小集合),求出以他为A大集合,需要减去的边数,维护最小值就可以了。

至于为什么要出度为0或者入度为0的小集合呢?因为如果是中间的某个集合,那么也要去掉的是  与当前DAG序列的所有入度为零的小集合 之间的那些连边,所以那样肯定减去的很多,而且可以直接归属在我们写的这种算法中。

当然也可以不用减法,直接A*B + A*(A-1) + B*(B-1) - m

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 2e5 + 5;
struct Edge {int to;int ne;
} e[MAX];
int head[MAX],tot;
int DFN[MAX],LOW[MAX],col[MAX],clk,index,scc,stk[MAX],vis[MAX];
ll cnt[MAX];
int n,m;
int in[MAX],out[MAX];
void add(int u,int v) {e[++tot].to = v;e[tot].ne = head[u];head[u] = tot;
}
void Tarjan(int x) {DFN[x] = LOW[x] = ++clk;vis[x] = 1;stk[++index] = x;for(int i = head[x]; ~i; i = e[i].ne) {int v = e[i].to;if(!DFN[v]) {Tarjan(v);LOW[x] = min(LOW[x],LOW[v]);}else if(vis[v]) LOW[x] = min(LOW[x],DFN[v]);}if(LOW[x] == DFN[x]) {scc++;while(1) {int tmp = stk[index];index--;vis[tmp] = 0;col[tmp] = scc;cnt[scc]++;if(tmp == x) break;}}
}
void init() {memset(head,-1,sizeof head);tot = 0;for(int i = 1; i<=n; i++) {DFN[i] = LOW[i] = cnt[i] = 0;in[i] = out[i] = 0;}clk = 0;index = 0;scc = 0;
}
int main()
{int t,iCase=0;cin>>t;while(t--) {scanf("%d%d",&n,&m);init();for(int a,b,i = 1; i<=m; i++) {scanf("%d%d",&a,&b);add(a,b);}for(int i = 1; i<=n; i++) {if(!DFN[i]) Tarjan(i);}if(scc == 1) {printf("Case %d: -1\n",++iCase);continue;}for(int u = 1; u<=n; u++) {for(int i = head[u]; ~i; i = e[i].ne) {int v = e[i].to;if(col[u] != col[v]) {out[col[u]]++;in[col[v]]++;}}}ll minn = n;for(int i = 1; i<=scc; i++) {if(in[i] == 0 || out[i] == 0) {minn = min(minn,cnt[i]);}} ll ans = 1LL * n * (n-1) - m;//最多还能增加这些边 printf("Case %d: %lld\n",++iCase,ans - minn * (n-minn) );}return 0 ;
}
/*
14:36 - 14:53
*/

【HDU - 4635】Strongly connected(缩点,新图性质,建图,Tarjan求强连通分量)相关推荐

  1. HDU 4635 Strongly connected(缩点、最多可加边数使得仍然非强连通)

    整理的算法模板合集: ACM模板 HDU 4635 Strongly connected Give a simple directed graph with N nodes and M edges. ...

  2. The King’s Problem(tarjan求强连通分量缩点+匈牙利求有向无环图的最小路径覆盖)

    Link:http://acm.hdu.edu.cn/showproblem.php?pid=3861 The King's Problem Time Limit: 2000/1000 MS (Jav ...

  3. 图论 —— 图的连通性 —— Tarjan 求强连通分量

    [概述] Tarjan 算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树. 搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量. [ ...

  4. HDU - 4635 Strongly connected(强连通缩点+数学+思维)

    题目链接:点击查看 题目大意:给出一个由n个点和m条边构成的无向图,现在问最多能添加几条边,能使得原图仍然不是强连通图,若原图初始时就是强连通图,直接输出-1 题目分析:首先对于原图来说,肯定会有一些 ...

  5. HDU 4635 Strongly connected

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4635 解题思路: 题目大意是你能最多能添加多少边,使的这个图不是强连通图.其临界条件是差一条边成强连通图 ...

  6. hdu 1269(Tarjan求强连通分量)

    这道题目就是求强连通分量... 这里采用的是Tarjan算法:http://m.blog.csdn.net/blog/qq574857122/16361033 AC代码: #include<io ...

  7. hdu 1269 tarjan求强连通分量

    tarjan求强连通分量的裸题复习,可当做模板. 1 #include <stack> 2 #include <cstdio> 3 #include <cstring&g ...

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

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

  9. tarjan对有向图的缩点(求强连通分量)

    tarjan对有向图的缩点(求强联通分量) 0x00 tarjan算法简介 tarjan算法是基于DFS的算法,核心在于巧妙的使用访问节点的时间戳 和 栈. tarjan算法可以用于求解: 最近公共祖 ...

最新文章

  1. XML,JOSN,YAML三种文件类型的区别
  2. 在Linux终端下查看GPU正常使用的情况
  3. react-router的基础知识
  4. Linux基础-兄弟连Linux
  5. Logback 配置文件例子
  6. Gulp 之图片压缩合并
  7. IoU 判断矩形区域重叠
  8. 做一个java项目要经过那些正规的步骤
  9. java 基础知识部分提炼
  10. C语言高级编程:char、signed char 和 unsigned char的使用区别
  11. c语言鸢尾花智能分类,基于LogisticRegression的鸢尾花分类
  12. Win10应用商店无法下载XBOX怎么办?
  13. 【办公技巧】Excel技巧 点击单元格打对勾(宏)
  14. 网工解惑:何为二层交换机,它与三层交换机的区别在哪里?
  15. 解决:java.lang.UnsupportedClassVersionError
  16. Android4.1
  17. 【微信小程序】创建项目
  18. java问卷导入excel_Java利用已有的Excel文件导出新的Excel
  19. 图书管理系统-数据库设计
  20. 国密算法--Openssl 实现国密算法(加密和解密)

热门文章

  1. 创建windows服务,定时监控网站应用程序池
  2. 第七章 假设检验(2)
  3. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第21篇]CRT算法如何提高RSA的性能?
  4. oracle自动备份定时任务,Oracle数据库定时自动备份批处理代码(Windows)
  5. 可信计算 沈昌祥_沈昌祥院士:用主动免疫可信计算构筑车联网安全防线
  6. java序列化写法_java-spark的各种常用算子的写法
  7. 前驱和后驱什么意思_为什么只有豪车才敢用后驱
  8. INTEL和AMD两大巨头的前身
  9. PJSIP UA分析(1)--PJSUA主函数
  10. xLite连接asterisk提示sip408错误