HDU 4635:Strongly connected(强连通入门)
来源:互联网 发布:解析域名 编辑:程序博客网 时间:2024/06/06 00:46
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4635
AC代码:
/*problem description:Give a simple directed graph with N nodes and M edges,a simple directed graph is defined as graph without duplicate edges and self loop.please program to calculate 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. 翻译:给出一个N个点,M条边的有向图简单图,简单图被定义为没有重边和自环的图,现在请 你编程计算最多加多少边,可以使图仍然使简单图,且图不使强连通图。 解题思路:对于一个N个节点的有向强连通简单图来说,最多有N*(N-1)条边,由于图中已经存在 M条边,因此还剩余N*(N-1)-M条,我们就需要在剩余的这些边中删除一些边,使得图中边数最 多且图不是强连通。如果想要最大的不是强连通的图,我们就让图中有两个强连通分量就可以了, 因此我们就来缩点,并且要保存下来强连通分量里面的顶点的个数。我们要找到那些出度或入度 为0的新点(强连通分量构成的一点),设其内部点数为nodenum,我们要找到nodenum*(N-nodenum) 的最小值,然后用N*(N-1)-M减去这个最小值即可。 原因是除了这个点外,其他的连通分量任意两点之间都保证有边,而对于这个连通分量,它可能是 入度为0的点,或出度为0的点,如果是入度为0的点,则不能从其他强连通分量往这里个分量里面 引边,则损失的边数是nodenum*(N-nodenum).同样如果这个点是出度为0的点,则不允许在从当前 强连通分量往别的连通分量发出边,损失的是node*(N-nodenum),所以找出度或入度为0的顶点中 node*(N-nodenum)的最小值。*/#include <iostream>#include <stdio.h>#include <string.h>#define inf 9999900020using namespace std;const int maxn = 100010;const int maxm = 100010;long long N,M;int Stack[maxn]; ///栈int inStack[maxn]; ///标记节点是否在栈中int dfn[maxn]; ///访问节点的时间标记int low[maxn]; ///类似并查集合并数组int head[maxn]; ///类似链表头结点的数组long long num[maxn]; ///统计强连通分量中的节点个数int inDegree[maxn]; ///统计节点的入度int outDegree[maxn]; ///统计节点的出度int belong[maxn]; ///某个节点所书强连通分量的编号int edgeNumber,time,cnt,top; //四个变量分别是图边数,时间戳,强连通分量个数,栈顶指针//边节点struct Edge{ int u; int v; int nex;}edge[maxm];//加边函数void addEdge(int u,int v){ edge[edgeNumber].u = u; edge[edgeNumber].v = v; edge[edgeNumber].nex = head[u]; head[u] = edgeNumber++;}///强连通算法找强连通分量void tarjan(int u){ low[u] = dfn[u] = ++time; Stack[++top] = u; inStack[u] = 1; for(int i = head[u]; i != -1; i = edge[i].nex) { int v = edge[i].v; if(!dfn[v]) { tarjan(v); low[u] = min(low[u],low[v]); } else if(inStack[v]) { low[u] = min(low[u],dfn[v]); } } if(dfn[u]==low[u]) { cnt++; int temp; do { temp = Stack[top--]; num[cnt]++; inStack[temp] = 0; belong[temp] = cnt; }while(temp != u); }}///求解void solve(){ top = time = cnt = 0; memset(num,0,sizeof(num)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); for(int i = 1; i <= N; i++) { if(!dfn[i]) { tarjan(i); } }}int main(){ int T,Case=0; scanf("%d",&T); while(T--) { scanf("%lld%lld",&N,&M); memset(head,-1,sizeof(head)); edgeNumber = 0; int u,v; for(int i = 1; i <= M; i++) { scanf("%d%d",&u,&v); addEdge(u,v); } solve(); if(cnt == 1) //图本身是强连通图 { printf("Case %d: -1\n",++Case); } else { memset(inDegree,0,sizeof(inDegree)); memset(outDegree,0,sizeof(outDegree)); for(int i = 0; i < edgeNumber; i++) { u = edge[i].u; v = edge[i].v; u = belong[u]; v = belong[v]; if(u != v) { outDegree[u]++; inDegree[v]++; } } long long ans = N*(N-1)-M; long long Min = inf; for(int i = 1; i <= cnt; i++) { if(inDegree[i]==0 || outDegree[i]==0) { Min = min(Min,num[i]*(N-num[i])); } } printf("Case %d: %lld\n",++Case,ans-Min); } } return 0;}
阅读全文
0 0
- HDU 4635:Strongly connected(强连通入门)
- HDU 4635 Strongly connected(强连通)
- hdu 4635 Strongly connected 强连通
- hdu 4635 Strongly connected (强连通分量)
- hdu-4635-Strongly connected-强连通分量
- HDU 4635 Strongly connected 强连通
- HDU 4635 Strongly connected(强连通分量)
- 【强连通】 HDU 4635 Strongly connected
- HDU 4635 - Strongly connected(强连通)
- HDU 4635 Strongly connected 强连通
- HDU 4635 Strongly connected(强连通)经典
- HDU 4635 Strongly connected(强连通分量)
- HDU-4635-Strongly connected(强连通分量)
- hdu 4635 Strongly connected(连通分量)
- hdu 4635 Strongly connected (tarjan强连通分量)
- hdu 4635 Strongly connected(强连通+缩点)
- hdu 4635 Strongly connected (强连通分量缩点)
- HDU 4635 Strongly connected(强连通分量+缩点)
- 那些年、一起追过的Spring--(5)----AOP
- maven 解决架包冲突
- 欢迎使用CSDN-markdown编辑器
- CentOS中MySQL安装
- 【学习摘记】马士兵Servlet&JSP_课时4_配置第一个servlet文件
- HDU 4635:Strongly connected(强连通入门)
- 多线程编程学习一(Java多线程的基础)
- VB.NET版机房收费系统——三层登录
- Android Error-AndroidStudio解决Minimum supported Gradle version is 3.3. Current version is 2.14.1问题
- http响应状态码大全
- Java高并发编程
- 背包dp之分组背包
- oracle基本操作命令
- 计算机英语(第四版)