Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)

Total Submission(s): 2487    Accepted Submission(s): 386

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 notadjacent
in G. 



Now you are given an undirected graph G of N nodes
and M bidirectional
edges of unit length.
Consider the complement of G,
i.e., H.
For a given vertex S on H,
you are required to compute the shortest distances from S to
all N−1 other
vertices.
 
Input
There are multiple test cases. The first line of input is an integer T(1≤T<35) denoting
the number of test cases. For each test case, the first line contains two integers N(2≤N≤200000) and M(0≤M≤20000).
The following M lines
each contains two distinct integers u,v(1≤u,v≤N) denoting
an edge. And S (1≤S≤N) is
given on the last line.
 
Output
For each of T test
cases, print a single line consisting of N−1 space
separated integers, denoting shortest distances of the remaining N−1 vertices
from S (if
a vertex cannot be reached from S, output ``-1" (without quotes) instead) in ascending order of vertex number.
 
Sample Input
  1. 1
  2. 2 0
  3. 1
 
Sample Output
  1. 1
 

【题解】

补图:

在完全图的基础上,把我们在这题中输入的边给去掉。剩余的图就是输入的图的补图。然后可以理解为,原来出现过的边在补图中都不会出现了。

在补图上做最短路。(边权为单位长度)

这题需要分两种情况来做。

1.

m<n-1;

则我们输入的图肯定是不连通的图。因为少于n-1条边你没办法使一张图连通.

这个时候节点的数量可能达到20万。你不可能写34组的dijkstra..而且每组都20万。

然后我们就有特殊的技巧了。

这是一种情况。

可以看到边的数目小于n-1条。

然后我们考虑一下它的补图,因为有一个点肯定是和所有的其他点都没有联通的。在这里就是4号节点。那么我把它和其他的点都连上,如下图

但是注意我还没有把其他边连上。这还不是它的补图。

但我们却由此得到一个思路。那就是所有的点都可以经过4号节点再多走一步到达其他任意一个节点。也就是说花费最多是2.

那有哪一些点到其他点的花费是1呢?

就是那些一开始在原图上没有和起点直接相连的点

假设起点是3.

那么完整的补图会是这样的

可以看到,原图上未和3号节点直接相连的节点与3的距离都是1.

这是因为。如果3号节点一开始没有和任何节点相连。那么补图上。

3号节点是会和其他所有节点都连上一条边的,也就是距离为1

但是如果有节点和3号节点相连。那么在补图上就不能存在一条边由3号节点直接指向那个节点了(即不存在距离为1的代价直接从3号节点到达那个点)

而我们刚才的分析已经得到最大的代价为2,即把那个一开始谁都没连过的节点作为中间节点走两步到达目标。

而m < n-1保证了有那样一个一开始谁都没连过的节点。

2.

m>=n-1;

这下你可说不准图有没有联通了。那该怎么办呢?

注意到n<=m+1.而m最大为20000;实际上我们已经可以用dijkstra来解决这个问题了。

这是它的能力范围之内的事情了。

从起点开始进行dijkstra算法就可以了。

详细的过程看代码注释。

题目的数据显示在n-1<=m的时候n最大值没有超过6000;

【代码】

  1. #include <cstdio>
  2. #include <cstring>
  3.  
  4. int T,n,m,bian[25000][2],s,dis[5500+100],w[6000][6000];
  5. bool linjin[200001+100],haved[5500+100];
  6.  
  7. const int MAX_N = 2100000000/3;//这是给dis数组一开始赋值用的玩意,就是一个很大的值。
  8.  
  9. void input_data()
  10. {
  11. scanf("%d%d",&n,&m);//输入n个点m条边。
  12. for (int i = 1;i <= m;i++)//输入m条边。
  13. scanf("%d%d",&bian[i][0],&bian[i][1]);
  14. scanf("%d",&s);//输入起点。
  15. }
  16.  
  17. void get_ans()
  18. {
  19. if (m < n-1) //如果这张原图是不可能联通的。
  20. {
  21. for (int i = 1;i <= m;i++)//看下有没有和起点相连的点。
  22. {
  23. if (bian[i][0] == s)
  24. linjin[bian[i][1]] = true;//如果和起点相连那么从起点到它的最短距离就只能是2
  25. if (bian[i][1] == s)
  26. linjin[bian[i][0]] = true;
  27. }
  28. bool flag = false;//这个flag用来判断要不要输出空格。
  29. for (int i = 1;i <= n;i++)
  30. if (i!=s)//如果不是起点,就要输出一些东西了
  31. {
  32. if (flag)
  33. printf(" ");
  34. if (linjin[i])
  35. printf("2");//如果这个点和起点相连。则最短的距离只能是2
  36. else
  37. printf("1");//如果不和起点相连。那么就可以存在一条边直接从起点指向该点。
  38. flag = true;//判断已经输出过一个答案。下次要输出空格了。
  39. }
  40. printf("\n");//输出一个空行
  41. }
  42. else //n <= m-1的情况
  43. {//在这个情况下n的最大值不超过5500;(数据显示)
  44. for (int i = 1;i <= n;i++)
  45. for (int j = 1;j <= n;j++)//一开始先构造出一个完全图。
  46. if (i!=j)
  47. w[i][j] = 1;//任意两点之间的距离除了两个相同的点的距离外都为1.
  48. else
  49. w[i][j] = 0;
  50. for (int i = 1;i <= m;i++) //然后输入的边是原图的边,它在补图里面就是不存在的了。
  51. {
  52. w[bian[i][0]][bian[i][1]] = MAX_N;//置为一个很大的数就可以了。
  53. w[bian[i][1]][bian[i][0]] = MAX_N;
  54. }
  55. for (int i = 1;i <= n;i++)//先置起点到所有的点的距离为起点到该点的距离。
  56. {
  57. dis[i] = w[s][i];
  58. haved[i] = false;//置该点还不是最短距离。
  59. }
  60. haved[s] = true;//起点到起点已经是最短距离了。
  61. for (int i = 1;i <= n;i++)
  62. {
  63. int k = -1,min = MAX_N;
  64. for (int j = 1;j <= n;j++)//找到离起点最近的点。(且要求它之前没有别用来更新过。)
  65. if (!haved[j] && dis[j] < min)
  66. {
  67. min = dis[j];
  68. k = j;
  69. }
  70. if (k == -1)//如果没找到就说明全部找完直接结束
  71. break;
  72. haved[k] = true;//否则就标记这个节点已经被用来更新过了。下次就不会再用到它了。
  73. for (int j = 1;j <= n;j++) //如果之前没有用过这个点更新,且需要更新
  74. if (!haved[j] && (dis[j] > dis[k] + w[k][j]))
  75. dis[j] = dis[k] + w[k][j];//则更新
  76. }
  77. bool flag = false;//flag依旧是用来控制输出的。
  78. for (int i = 1;i <= n;i++)
  79. if (i!=s)
  80. {
  81. if (flag) printf(" ");//如果之前已经输出过一个了,则需要输出一个空格。
  82. if (dis[i] >= MAX_N) //如果是一个“无穷大”的值就直接输出-1,否则输出最短路。
  83. printf("-1");
  84. else
  85. printf("%d",dis[i]);
  86. flag = true;//标记已经输出过答案。
  87. }
  88. printf("\n");
  89. }
  90. }
  91.  
  92. int main()
  93. {
  94. //freopen("F:\\rush.txt","r",stdin);
  95. //freopen("F:\\rush_out.txt","w",stdout);
  96. scanf("%d",&T);//输入T组数据。
  97. while (T--)
  98. {
  99. memset(linjin,0,sizeof(linjin));
  100. input_data();
  101. get_ans();
  102. }
  103. return 0;
  104. }

【icpc网络赛大连赛区】Sparse Graph的更多相关文章

  1. 【2018ACM/ICPC网络赛】沈阳赛区

    这次网络赛没有打.生病了去医院了..尴尬.晚上回来才看了题补简单题. K  Supreme Number 题目链接:https://nanti.jisuanke.com/t/31452 题意:输入一个 ...

  2. Ryuji doesn't want to study 2018徐州icpc网络赛 树状数组

    Ryuji is not a good student, and he doesn't want to study. But there are n books he should learn, ea ...

  3. 【2018ACM/ICPC网络赛】焦作赛区

    A Magic Mirror 题目链接:https://nanti.jisuanke.com/t/31710 题意:输入字符串,如果是“Jessy”就输出“Good Guy!",否则输出“D ...

  4. 【2018ACM/ICPC网络赛】徐州赛区

    呃.自闭了自闭了.我才不会说我写D写到昏天黑地呢. I  Characters with Hash 题目链接:https://nanti.jisuanke.com/t/31461 题意:给你一个字符串 ...

  5. Trace 2018徐州icpc网络赛 (二分)(树状数组)

    Trace There's a beach in the first quadrant. And from time to time, there are sea waves. A wave ( xx ...

  6. Supreme Number 2018沈阳icpc网络赛 找规律

    A prime number (or a prime) is a natural number greater than 11 that cannot be formed by multiplying ...

  7. Trace 2018徐州icpc网络赛 思维+二分

    There's a beach in the first quadrant. And from time to time, there are sea waves. A wave ( xx , yy) ...

  8. Features Track 2018徐州icpc网络赛 思维

    Morgana is learning computer vision, and he likes cats, too. One day he wants to find the cat moveme ...

  9. 2017 ICPC网络赛(西安)--- Xor

    题目连接 Problem There is a tree with n nodes. For each node, there is an integer value ai, (1≤ai​≤1,000 ...

随机推荐

  1. python运算符优先级表

    运算符 描述 lambda Lambda表达式 or 布尔“或” and 布尔“与” not x 布尔“非” in,not in 成员测试 is,is not 同一性测试 <,<=,> ...

  2. amazeui学习笔记二(进阶开发2)--Web组件简介Web Component

    amazeui学习笔记二(进阶开发2)--Web组件简介Web Component 一.总结 1.amaze ui:amaze ui是一个web 组件, 由模板(hbs).样式(LESS).交互(JS ...

  3. 洛谷——P1046 陶陶摘苹果

    https://www.luogu.org/problem/show?pid=1046 题目描述 陶陶家的院子里有一棵苹果树,每到秋天树上就会结出10个苹果.苹果成熟的时候,陶陶就会跑去摘苹果.陶陶有 ...

  4. 1.6 Python基础知识 - for循环

    在循环语句中,除了while循环外,还有一种循环叫for循环的循环语句,for循环语句用于遍历可迭代(什么是迭代?以及迭代的相关知识,我们到后面再进行阐述,这里只要记住就可以了.)对象集合中的元素,并 ...

  5. QSYS系统简介

    QSYS是SoPC Builder的新一代产品. QSYS系统集成工具自动生成互联逻辑,连接IP和子系统 QSYS的设计理念是提高设计抽象级,从而使机器自动生成底层代码. Altera的Avalon总 ...

  6. java调用C++的过程

    转自https://blog.csdn.net/yjhdxflqm/article/details/50503551 jni是java和C.C++通信的桥梁. java适合写上层的应用,C.C++适合 ...

  7. 【Codeforces Round #445 (Div. 2) C】 Petya and Catacombs

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 看看时间戳为i的点有哪些. 每次优先用已经访问过的点. 如果不行就新创一个点. 注意新创点的时间戳也是i. [代码] #includ ...

  8. 打开utf-8文件乱码的解决方法

    gvim一直用的好好的,但是今天看一网友贴出来的代码时,却发现中文显示乱码了.... 使用notepad++打开,右下角显示是utf-8 w/0 BOM. 马上放狗, 发现解决方法如下:   在_vi ...

  9. Qt5 UI信号、槽自动连接的控件重名大坑(UI生成的槽函数存在一个隐患,即控件重名。对很复杂的控件,不要在 designer 里做提升,而是等到程序启动后,再动态创建,可以避免很多问题)

    对Qt5稍有熟悉的童鞋都知道信号.槽的自动连接机制.该机制使得qt designer 设计的UI中包含的控件,可以不通过显式connect,直接和cpp中的相应槽相关联.该机制的详细文章见 http: ...

  10. HttpClient证书回调问题解决

    /// <summary>        /// httpclient请求        /// </summary>        /// <param name=&q ...