HDOJ 5409 CRB and Graph 无向图缩块

无向图缩块后,以n所在的块为根节点,dp找每块中的最大值.

对于每一个桥的答案为两块中的较小的最大值和较小的最大值加1

CRB and Graph

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 113    Accepted Submission(s): 41

Problem Description

A connected, undirected graph of N vertices
and M edges
is given to CRB.

A pair of vertices (u, v)
(u < v)
is called critical for edge e if
and only if u and v become
disconnected by removing e.

CRB’s task is to find a critical pair for each of M edges.
Help him!

Input

There are multiple test cases. The first line of input contains an integer T,
indicating the number of test cases. For each test case:

The first line contains two integers N, M denoting
the number of vertices and the number of edges.

Each of the next M lines
contains a pair of integers a and b,
denoting an undirected edge between a and b.

1 ≤ T ≤
12

1 ≤ N, M ≤ 105

1 ≤ a, b ≤ N

All given graphs are connected.

There are neither multiple edges nor self loops, i.e. the graph is simple.

Output

For each test case, output M lines, i-th
of them should contain two integers u and v,
denoting a critical pair (u, v)
for the i-th
edge in the input.

If no critical pair exists, output "0 0" for that edge.

If multiple critical pairs exist, output the pair with largest u.
If still ambiguous, output the pair with smallest v.

Sample Input

2
3 2
3 1
2 3
3 3
1 2
2 3
3 1

Sample Output

1 2
2 3
0 0
0 0
0 0

Author

KUT(DPRK)

Source

2015 Multi-University Training Contest 10

/* ***********************************************
Author        :CKboss
Created Time  :2015年08月22日 星期六 10时24分13秒
File Name     :HDOJ5409.cpp
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;

const int maxn=100100;

typedef long long int LL;
typedef pair<int,int> pII;

struct Edge
{
	int from,to,next,id;
}edge[maxn*2];

int Adj[maxn],Size,n,m;

void init()
{
	Size=0; memset(Adj,-1,sizeof(Adj));
}

void Add_Edge(int u,int v,int id)
{
	edge[Size].from=u;
	edge[Size].id=id;
	edge[Size].to=v;
	edge[Size].next=Adj[u];
	Adj[u]=Size++;
}

int Low[maxn],DFN[maxn],Stack[maxn],Belong[maxn];
int Index,top,scc;
bool Instack[maxn],vis[maxn],ve[maxn*2];

void Tarjan(int u,int fa)
{
	int v;
	Low[u]=DFN[u]=++Index;
	Stack[top++]=u;
	Instack[u]=true;

	for(int i=Adj[u];~i;i=edge[i].next)
	{
		v=edge[i].to;
		if(v==fa&&ve[edge[i].id]) continue;
		ve[edge[i].id]=true;
		if(!DFN[v])
		{
			Tarjan(v,u);
			Low[u]=min(Low[u],Low[v]);
		}
		else
		{
			Low[u]=min(Low[u],DFN[v]);
		}
	}
	if(Low[u]==DFN[u])
	{
		scc++;
		do
		{
			v=Stack[--top];
			Belong[v]=scc;
			Instack[v]=false;
		}while(v!=u);
	}
}

void scc_solve()
{
	memset(DFN,0,sizeof(DFN));
	memset(Instack,0,sizeof(Instack));

	Index=scc=top=0;
	memset(ve,0,sizeof(ve));

	for(int i=1;i<=n;i++)
	{
		if(!DFN[i]) Tarjan(i,i);
	}
}

int value[maxn];
vector<pII> G[maxn];
int ans[maxn][2];
int bian[maxn][2];
int MX[maxn];

void dfs(int u,int fa)
{
	MX[u]=value[u];
	for(int i=0,sz=G[u].size();i<sz;i++)
	{
		int v=G[u][i].first;
		if(v==fa) continue;
		dfs(v,u);
		MX[u]=max(MX[u],MX[v]);
	}
}

int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);

	int T_T;
	scanf("%d",&T_T);
	while(T_T--)
	{
		scanf("%d%d",&n,&m);
		init();
		for(int i=0;i<m;i++)
		{
			int a,b;
			scanf("%d%d",&a,&b);
			bian[i][0]=a; bian[i][1]=b;
			Add_Edge(a,b,i); Add_Edge(b,a,i);
		}
		scc_solve();

		/***************REBUILD**********************/

		memset(value,0,sizeof(value));
		memset(ans,0,sizeof(ans));
		int root=0;

		for(int i=1;i<=n;i++)
		{
			G[i].clear();
			int b=Belong[i];
			value[b]=max(value[b],i);
			if(value[b]==n) root=b;
		}

		//for(int i=1;i<=scc;i++) cout<<i<<" value: "<<value[i]<<endl;

		for(int i=0;i<m;i++)
		{
			int u=Belong[bian[i][0]];
			int v=Belong[bian[i][1]];
			if(u==v) continue;
			G[u].push_back(make_pair(v,i)); G[v].push_back(make_pair(u,i));
		}

		dfs(root,root);

		//for(int i=1;i<=scc;i++) { cout<<i<<" mx: "<<MX[i]<<endl; }

		for(int i=0;i<m;i++)
		{
			int u=Belong[bian[i][0]];
			int v=Belong[bian[i][1]];
			if(u==v)
			{
				puts("0 0"); continue;
			}
			else
			{
				int mx=min(MX[u],MX[v]);
				printf("%d %d\n",mx,mx+1);
			}
		}
	}

    return 0;
}
时间: 2024-10-13 04:55:54

HDOJ 5409 CRB and Graph 无向图缩块的相关文章

HDU 5409 CRB and Graph 双连通缩点 + st表

HDU 5409 显然要先双连通缩成一棵树. 然后对于树上的边才有答案. 对于一条边来说, 两侧的最大值分为mx1 , mx2 , 那么 u 一定是min(mx1, mx2), v 一定是 u + 1. 这个经过仔细分析一下就能得到, 然后按dfs序建个st表就好啦. #include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi firs

HDU 5409 CRB and Graph

题意: 给出一个无向图. 问删去每一条边后,是否出现一对(u,v) st 删去这条边后,u和v不连通,且u<v,若有多对,输出u最大的,然后v最小的. 数据范围10^5 思路: 首先显然先用tarjan处理处各个强连通块.顺便处理处每个块中的点编号最大的是多少.以belong[x]表示x这个点属于哪个块. 对于一条边,若他不是桥边,则删去他后不会出现不联通的u,v,结果是0 0 如果是桥边,就以(belong[x], belong[y])为边加入新图中 然后我们缩完了点获得了一棵树. 若是桥边:

hdu4612 无向图中任意添加一条边后使桥的数量最少 / 无向图缩点+求树的直径

题意如上,含有重边(重边的话,俩个点就可以构成了边双连通). 先缩点成树,在求数的直径,最远的连起来,剩下边(桥)的自然最少.这里学习了树的直径求法:第一次选任意起点U,进行bfs,到达最远的一个点v(level最深)该点必然是树的直径的一个端点,,再从该点出发,bfs,到最深的一点,该点深度就是直径.(证明:先假设u,是直径上一点,S,T是直径的端点,设v!=t,则有(V,U)+(U,S)>(T,U)+(U,S),矛盾,故t=v:若u不是直径上一点,设u到直径上的一点为x,同理易证. 最后 缩

背包DP HDOJ 5410 CRB and His Birthday

题目传送门 题意:有n个商店,有m金钱,一个商店买x件商品需要x*w[i]的金钱,得到a[i] * x + b[i]件商品(x > 0),问最多能买到多少件商品 01背包+完全背包:首先x == 1时,得到a[i] + b[i],若再买得到的是a[i],那么x == 1的情况用01背包思想,x > 1时就是在01的基础上的完全背包.背包dp没刷过专题,这么简单的题也做不出来:( /************************************************* Author

构造 HDOJ 5414 CRB and String

题目传送门 题意:给两个字符串s,t,可以在s字符串任意位置后面插入字符c(与前面的不同),问是否能够将s转换为t字符串 构造:首先lens > lent 或者 s[1] != t[1] 一定是No,然后t最前面相同字符长度的部分在s中要相同,否则不能插入,之后的部分只要相同的部分全部存在,不同的部分可以随便插 /************************************************* Author        :Running_Time* Created Time

hdu 4738 无向图缩点断桥 // 细节坑题

Caocao's Bridges 题意:给个无向图,求出边权最小的桥. 一看,直接缩点,若无桥,输出-1,有桥,遍历下边,更新最小..分分钟搞定,以为IA的..一交wa... 坑点:1:若原图不连通,则无须派人去!输出0!: 2:若桥的权是0,则还有派一个人把炸弹拿去,输出1! 3:有重边.(按多条边算). 哎!记住这个教训!以后做题 1:考虑边界或者特殊数据!(边权为0!n==1等) 2:考虑原图连通性!(这次考虑了原图就强连通..没有考虑根本不连通!) 3:重边.这题的重边是按重边算(不是一

hdoj 3435 A new Graph Game 【无向图判断权值最小哈密顿环】【KM算法】

A new Graph Game Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1934    Accepted Submission(s): 827 Problem Description An undirected graph is a graph in which the nodes are connected by undir

Codeforces Round #143 (Div. 2) E. Cactus 无向图缩环+LCA

E. Cactus A connected undirected graph is called a vertex cactus, if each vertex of this graph belongs to at most one simple cycle. A simple cycle in a undirected graph is a sequence of distinct vertices v1, v2, ..., vt (t > 2), such that for any i (

hdu4612 无向图中随意加入一条边后使桥的数量最少 / 无向图缩点+求树的直径

题意如上,含有重边(重边的话,俩个点就能够构成了边双连通). 先缩点成树,在求数的直径,最远的连起来,剩下边(桥)的自然最少.这里学习了树的直径求法:第一次选随意起点U,进行bfs,到达最远的一个点v(level最深)该点必定是树的直径的一个端点,,再从该点出发,bfs,到最深的一点.该点深度就是直径. (证明:先如果u.是直径上一点,S,T是直径的端点.设v!=t,则有(V,U)+(U,S)>(T,U)+(U,S),矛盾,故t=v:若u不是直径上一点.设u到直径上的一点为x.同理易证. 最后