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])为边加入新图中

然后我们缩完了点获得了一棵树.

若是桥边:太(wo)巧(tai)妙(chun)惹。

  首先达成共识:若i这个块中,最大的点为maxn[i],则点maxn[i]+1和不在i这个块中。

        同理若以maxn[i]表示i子树上的最大值,则点maxn[i]+1不在这i子树上

  然后处理:

  1.以n所在的块为根,处理这棵树。接下来都把块视为点了因为打字麻烦= =

  2.处理出maxn[i]为i的子树中值得最大值 即 maxn[i] = max{maxn[j] | i 是 j 的祖先},这个可以简单树形DP处理出。顺便处理出每个点的深度。

  3.接下来继续前面的枚举原图的每一条边。对于边两边的点:

    (1)属于同一个块,答案如上面说的

    (2)属于不同块。则设他们所在的块为u, v。可以知道在刚才那棵树中,u一定是v的父亲或者v一定是u的父亲(树上的边直接连接了他们),为了表达方便我们设u是父亲。删去边后变成了v子树以及除了v子树以外的一块。因为有maxn[v] <= maxn[u],且有maxn[v] + 1不在v子树上,所以maxn[v] +1一定在另一块上,也就是他们分开了,那么这是一组可行解。怎么证明是最大呢= =因为maxn[v]是v子树上最大值,没有别的值比他大了。。且不会选择出maxn[v] = n因为v一定是儿子,而n在整棵树的根上,他所在的块一定不是儿子。

大概说的挺清楚了吧,,啰嗦患者的日常= =

其他看代码吧,虽然注释也没多少= = 然后minn是没用的数组哈哈哈= =

  1 #include <cstring>
  2 #include <cstdio>
  3 #include <algorithm>
  4 using namespace std;
  5 const int N = 100005;
  6
  7 int head[N], maxn[N], minn[N], dfn[N], low[N], st[N], belong[N];
  8 int deep[N];
  9
 10 struct point{
 11     int u, v, next;
 12     point(){};
 13     point(int x, int y, int z){
 14         u=x, v = y, next = z;
 15     }
 16 }p[N<<1];
 17 int no, top, num, id;
 18 struct Ans{
 19     int x, y;
 20     Ans(){};
 21     Ans(int _u, int _v){
 22         x = _u; y = _v;
 23     }
 24 }ans[N];
 25 void init(){
 26     memset(head, -1, sizeof(head));
 27     memset(dfn, -1, sizeof(dfn));
 28     memset(maxn, 0, sizeof(maxn));
 29     memset(minn, 0x3f, sizeof(minn));
 30     no = id = num = top = 0;
 31 }
 32
 33 void add(int x, int y){
 34     p[no] = point(x, y, head[x]);
 35     head[x] = no++;
 36     p[no] = point(y, x, head[y]);   head[y] =no++;
 37 }
 38 //tarjan求强连通,belong[i]表示属于哪个块
 39 //记录每个块中编号最大值
 40 void tarjan( int x, int fa){
 41     int cnt = 0;
 42     low[x] = dfn[x] = ++num;
 43     st[++top] = x;
 44     int i, y;
 45     for(i = head[x]; i != -1; i = p[i].next){
 46         y = p[i].v;
 47         if(y == fa)continue;
 48         if(dfn[y] == -1)    {
 49             tarjan(y, x);
 50             low[x] = min(low[x], low[y]);
 51         }
 52         else low[x] = min(low[x], dfn[y]);
 53     }
 54     if(dfn[x] == low[x]){
 55         id ++;
 56         do{
 57             y = st[top--];
 58             belong[y] = id;
 59             maxn[id] = max(maxn[id], y);
 60             minn[id] = min(minn[id], y);
 61         }while(x != y);
 62     }
 63 }
 64 //maxn表示i 及其子树的最大值
 65 void dfs(int x, int fa){
 66     int i, y;
 67     for(i = head[x]; i != -1; i = p[i].next){
 68         y = p[i].v;
 69         if(y == fa) continue;
 70         deep[y] = deep[x] + 1;
 71         dfs(y, x);
 72         maxn[x] = max(maxn[x], maxn[y]);
 73     }
 74
 75 }
 76 int main(){
 77     int TC, n, m, i, x, y, u, v;
 78     scanf("%d", &TC);
 79     while(TC--){
 80         scanf("%d%d", &n, &m);
 81         init();
 82         for(i = 1; i <= m; i++){
 83             scanf("%d%d", &x, &y);
 84             add(x, y);
 85         }
 86         tarjan(1, 1);
 87
 88         m = no;
 89         no = 0;
 90         memset(head, -1, sizeof(head));
 91         //重新建出树
 92         for(i = 0; i < m; i+= 2){
 93             x = belong[p[i].u]; y = belong[p[i].v];
 94             //属于同一个块,非桥边,删了之后不出现不通的点
 95             if(x == y) ans[i/2] = Ans(0, 0);
 96             else {
 97                 ans[i/2] = Ans(x, y);
 98                 add(x, y);
 99             }
100         }
101         deep[1] = 0;
102         //以n所在的块为根,dfs这棵树,求出子树的maxn
103         dfs(belong[n], 0);
104         m >>= 1;
105         for(i = 0; i < m; i++){
106             if(ans[i].x == 0)   printf("0 0\n");
107             else{
108                 //因为只隔一条边
109                 u = ans[i].x;   v  = ans[i].y;
110                 if(deep[u] > deep[v]){
111                     printf("%d %d\n", maxn[u], maxn[u] + 1);
112                 }   else {
113                     printf("%d %d\n", maxn[v], maxn[v] + 1);
114                 }
115             }
116         }
117     }
118     return 0;
119 }
时间: 2024-10-12 12:21:15

HDU 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

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, undi

hdu 5412 CRB and Queries(线段树套笛卡尔树 - 动态区间第k大)

题目链接:hdu 5412 CRB and Queries 首先对所有出现过的值排序,建立线段树,每个线段树的节点是一棵笛卡尔树,笛卡尔树记录区间下标值. #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> using namespace std; #define lson(x) (x<<1) #define rson(x) ((x<<

hdu 1853 Cyclic Tour &amp;&amp; hdu 3435 A new Graph Game(简单KM算法)

Cyclic Tour Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others) Total Submission(s): 1478    Accepted Submission(s): 750 Problem Description There are N cities in our country, and M one-way roads connecting them. Now L

Hdu 5416 CRB and Tree (bfs)

题目链接: Hdu 5416 CRB and Tree 题目描述: 给一棵树有n个节点,树上的每条边都有一个权值.f(u,v)代表从u到v路径上所有边权的异或值,问满足f(u,v)==m的(u, v)有多少中情况(u, v有可能相同)? 解题思路: 由于xor的特殊性质.x^x=0,对于求f(u, v) == f(u, 1) ^ f(1, u). 又因为x^y == z可以推出x^z == y,对于f(u, 1) ^ f(1, v) == m可以转化为m ^ f(1, v) == f(u, 1)

Hdu 5407 CRB and Candies (找规律)

题目链接: Hdu 5407 CRB and Candies 题目描述: 给出一个数n,求lcm(C(n,0),C[n,1],C[n-2]......C[n][n-2],C[n][n-1],C[n][n])%(1e9+7)是多少? 解题思路: 刚开始的时候各种开脑洞,然后卡题卡的风生水起.最后就上了数列查询这个神奇的网站,竟然被我找到了!!!!就是把题目上给的问题转化为求lcm(1, 2, 3, 4 ...... n-2, n-1, n, n-1) / (n+1),扎扎就打了两个表一个lcm[n

hdu 5412 CRB and Queries

题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5412 CRB and Queries Description There are $N$ boys in CodeLand. Boy i has his coding skill $A_{i}$. CRB wants to know who has the suitable coding skill. So you should treat the following two types of qu

HDU 5412 CRB and Queries(区间第K大 树套数 按值建树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5412 Problem Description There are N boys in CodeLand. Boy i has his coding skill Ai. CRB wants to know who has the suitable coding skill. So you should treat the following two types of queries. Query 1:

HDU 5876:Sparse Graph(BFS)

http://acm.hdu.edu.cn/showproblem.php?pid=5876 Sparse Graph Problem Description In graph theory, the complement of a graph G is a graph H on the same vertices such that two distinct vertices of H are adjacent if and only if they are not adjacent in G