HDU 4635 Strongly connected 连通图
2016-05-05 12:20
453 查看
题目描述:
DescriptionGive 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
题目分析:
题目大意就是有一个有向图,你可以至多加多少条边使这个有向图依然不能强连通。若原图就是强连通图,则输出-1。先用Tarjan算连通分支,如果只有一个连通分支,说明这是强连通图,输出-1。
接下来把问题等价转化成一个完全图,减去最少的边使这个图不是强连通图。将各个强连通分量缩成点,去除所有强联通分量中含有点数最少的点的所有进边,就能得出答案。
代码如下:
#include <stdio.h> #include <algorithm> #include <string.h> #include <iostream> #include <map> #include <vector> #include <queue> #include <set> #include <string> #include <math.h> const int MAXN=100010; const int INF= 0x3f3f3f3f; typedef long long LL; using namespace std; struct Edge { int to,next; }edge[MAXN]; int head[MAXN],tot; int low[MAXN],dfn[MAXN],stack[MAXN],belong[MAXN]; int index,top; int scc; bool instack[MAXN]; int num[MAXN];//各个强连通分量包含的点的个数 int id[MAXN],od[MAXN];//出度和入度 void init() { tot=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v) { edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } void tarjan(int u)//kuangbin模板 { int v; low[u]=dfn[u]=++index; stack[top++]=u; instack[u]=true; for(int i=head[u]; i!=-1; i=edge[i].next) { v=edge[i].to; if (!dfn[v]) { tarjan(v); if (low[u]>low[v]) low[u]=low[v]; } else if (instack[v] && low[u]>dfn[v]) low[u]=dfn[v]; } if (low[u]==dfn[u]) { scc++; do { v=stack[--top]; instack[v]=false; belong[v]=scc; num[scc]++; } while(v!=u); } } void solve(int n) { memset(dfn,0,sizeof(dfn)); memset(instack,false,sizeof(instack)); memset(num,0,sizeof(num)); index=scc=top=0; for(int i=1; i<=n; i++) { if (!dfn[i]) tarjan(i); } } int T; int n,m; int main() { scanf("%d",&T); for(int t=1; t<=T; t++) { init(); scanf("%d%d",&n,&m); for(int i=0; i<m; i++) { int x,y; scanf("%d%d",&x,&y); addedge(x,y); } solve(n); printf("Case %d: ",t); if (scc==1) {printf("-1\n");continue;} memset(id,0,sizeof(id)); memset(od,0,sizeof(od)); for(int u=1; u<=n; u++) { for(int i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].to; if (belong[u]!=belong[v]) { od[belong[u]]++; id[belong[v]]++; } } } LL sss=(LL)n*(n-1)-m; LL ans=0; for(int i=1; i<=scc; i++) { if(id[i]==0 || od[i]==0) ans=max(ans,sss-(LL)num[i]*(n-num[i])); } printf("%lld\n",ans); } return 0; }
相关文章推荐
- HTTP详解(2)-请求、响应、缓存
- LeetCode 017 Letter Combinations of a Phone Number
- HDU1024 Max Sum Plus Plus //DP
- 卷积码
- 489 - Hangman Judge
- Java 容器(三) Set
- LeetCode 256. Paint House
- 卡特兰数
- 用PHP将网页上的Canvas图像保存到服务器上的方法
- Javascript函数----操作DOM文档对象模型
- 从一个队列中取出一个元素再放回去同时保持原来的顺序,不申请非必需的空间存储队列中的元素
- ARC下OC对象和CF对象之间的桥接(bridge)
- django ATOMIC_REQUESTS
- android:ViewPager自动轮播图(简单版)
- 机器学习----SVM(2)从原始问题到对偶问题的转换
- PHP Warning之max_input_vars
- Node.js express NPM start error, Exit Status 8
- Swift-字典
- Python实现HTTP-Basic认证登陆
- 《java入门第一季》之面向对象(继承)