zoukankan      html  css  js  c++  java
  • HDU 5876 Sparse Graph 【补图最短路 BFS】(2016 ACM/ICPC Asia Regional Dalian Online)

    Sparse Graph

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
    Total Submission(s): 689    Accepted Submission(s): 238


    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 N1 other vertices.
     
    Input
    There are multiple test cases. The first line of input is an integer T(1T<35) denoting the number of test cases. For each test case, the first line contains two integers N(2N200000) and M(0M20000). The following M lines each contains two distinct integers u,v(1u,vN) denoting an edge. And S (1SN) is given on the last line.
     
    Output
    For each of T test cases, print a single line consisting of N1 space separated integers, denoting shortest distances of the remaining N1 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 2 0 1
     
    Sample Output
    1
     
    Source
     
    Recommend
    wange2014   |   We have carefully selected several similar problems for you:  5877 5876 5875 5874 5873 
     
    Statistic | Submit | Discuss | Note

    题目链接:

      http://acm.hdu.edu.cn/showproblem.php?pid=5876

    题目大意:

      给你N个点M条无向边的一张图G(2<=N<=200000,0<=M<=20000),并给定起点S,边权均为1,求在这张图的补图H上S到其他N-1个点的最短路,无法到达为-1。

      补图:在原图G上X和Y之间有一条边,则补图上X和Y之间没有相连的边,在原图X和Z之间没边,那么在补图上X和Z之间有一条边。

    题目思路:

      【补图最短路】【宽搜】

      比赛的时候数据范围写错了导致队列开小了。WA了。。然而队友神奇的map[5500][5500]居然过了。。不是很懂。。

      首先分析一下原图G,如果存在孤立点X(不与任何点相连),那么在补图上这个点X与其他所有的点相连,所以d[X]=1。

        对于其余点Y,若Y与S相连则Y的最短路为S->X->Y,d[Y]=2,否则即为S->Y,d[Y]=1。(当N>M+1时必有孤立点)

      再考虑没有孤立点的情况,对于原图G,先将S能够到达的点和不能到达的点分为两个集合T和Q,易知Q中所有的点d[i]=1

      接着,将Q中的所有点做一次宽搜(最短路SPFA),每个点能够到达的在T中的点d++,Q中所有的点都做完后判断T中的点

      对于T中的点X,如果X在原图不能被Q中所有的点走到,那么在补图中一定有一条边从Q中的点Y连向X,则d[X]=d[Y]+1,

      如果被Q中所有点走到,那么这个点继续留在X中等待下一次。

      做完一次后,继续对新加入Q中的节点做宽搜(最短路SPFA),直到没有新节点加入Q。

      如果此时T中还有点则为走不到的,d=-1。

      最后输出答案即可。注意多余空格会PE。

      注释见代码。

      1 //
      2 //by coolxxx
      3 //#include<bits/stdc++.h>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<string>
      7 #include<iomanip>
      8 #include<map>
      9 #include<stack>
     10 #include<queue>
     11 #include<set>
     12 #include<bitset>
     13 #include<memory.h>
     14 #include<time.h>
     15 #include<stdio.h>
     16 #include<stdlib.h>
     17 #include<string.h>
     18 //#include<stdbool.h>
     19 #include<math.h>
     20 #define min(a,b) ((a)<(b)?(a):(b))
     21 #define max(a,b) ((a)>(b)?(a):(b))
     22 #define abs(a) ((a)>0?(a):(-(a)))
     23 #define lowbit(a) (a&(-a))
     24 #define sqr(a) ((a)*(a))
     25 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
     26 #define mem(a,b) memset(a,b,sizeof(a))
     27 #define eps (1e-10)
     28 #define J 10000
     29 #define mod 1000000007
     30 #define MAX 0x7f7f7f7f
     31 #define PI 3.14159265358979323
     32 #pragma comment(linker,"/STACK:1024000000,1024000000")
     33 #define N 200004
     34 #define M 20004
     35 using namespace std;
     36 typedef long long LL;
     37 double anss;
     38 LL aans;
     39 int cas,cass;
     40 int n,m,lll,ans;
     41 int S;
     42 int last[N],d[N];
     43 char ch;
     44 int q[M],t[M];
     45 struct xxx
     46 {
     47     int to,next;
     48 }a[M<<1];
     49 bool mark[N];
     50 void add(int x,int y)
     51 {
     52     a[++lll].to=y;
     53     a[lll].next=last[x];
     54     last[x]=lll;
     55 }
     56 void work1()
     57 {
     58     int i;
     59     for(i=1;i<=n;i++)d[i]=1;
     60     for(i=last[S];i;i=a[i].next)d[a[i].to]+=1;//孤立点情况与S相连的点答案为2,其余为1
     61     for(i=1;i<=n;i++)
     62     {
     63         if(i==n || (i==n-1 && S==n))ch='
    ';
     64         else ch=' ';
     65         if(i==S)continue;
     66         printf("%d%c",d[i],ch);
     67     }
     68 }
     69 void spfa()
     70 {
     71     int i,now,to,l=1,r=1,x=0,y=0,sz;
     72     mem(mark,0);
     73     for(i=1;i<=n;i++)d[i]=mark[i]=1;//初始化
     74     q[1]=S;mark[S]=1;d[S]=0;
     75     for(i=last[S];i;i=a[i].next)mark[a[i].to]=0;
     76     for(i=1;i<=n;i++)//将所有点分成两类
     77     {
     78         if(i==S)continue;
     79         if(mark[i])
     80             q[++r]=i;//与S不相连的,d=1
     81         else
     82             t[++y]=i;//与S相连的,需要进一步判断
     83     }
     84     while(l<r)
     85     {
     86         while(l<r)//将Q中新加入的点now往T集合的点走,每走到一个在T中的点x,d[x]++
     87         {
     88             now=q[++l];
     89             for(i=last[now];i;i=a[i].next)
     90             {
     91                 to=a[i].to;
     92                 if(mark[to])continue;
     93                 d[to]++;
     94             }
     95         }
     96         sz=r;//sz为Q集合的大小,如果在T中的点x在补图中有连向Q的边,那么d[x]<sz(在原图上x不被所有Q中的点走到)
     97         for(i=1,x=0;i<=y;i++)
     98         {
     99             now=t[i];
    100             if(d[now]==sz)
    101                 t[++x]=now;//被所有点走到,继续留在T中
    102             else
    103             {
    104                 q[++r]=now;//将这个点加入Q中
    105                 d[now]=d[q[l]]+1;//这个点的距离为上一个距离+1
    106                 mark[now]=1;//标记为在Q中
    107             }
    108         }
    109         y=x;//T的新大小
    110     }
    111     for(i=1;i<=y;i++)d[t[i]]=-1;//若Q中的点都遍历完,T中还有剩余的点,则为走不到的点,d=-1
    112     for(i=1;i<=n;i++)
    113     {
    114         if(i==n || (i==n-1 && S==n))ch='
    ';
    115         else ch=' ';
    116         if(i==S)continue;
    117         printf("%d%c",d[i],ch);
    118     }
    119 }
    120 int main()
    121 {
    122     #ifndef ONLINE_JUDGE
    123 //    freopen("1.txt","r",stdin);
    124 //    freopen("2.txt","w",stdout);
    125     #endif
    126     int i,j,k;
    127     int x,y,z;
    128 //    init();
    129     for(scanf("%d",&cass);cass;cass--)
    130 //    for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
    131 //    while(~scanf("%s",s))
    132 //    while(~scanf("%d",&n))
    133     {
    134         lll=cas=0;mem(last,0);mem(mark,0);
    135         scanf("%d%d",&n,&m);
    136         for(i=1;i<=m;i++)
    137         {
    138             scanf("%d%d",&x,&y);
    139             add(x,y),add(y,x);
    140             if(!mark[x])mark[x]=1,cas++;
    141             if(!mark[y])mark[y]=1,cas++;
    142         }
    143         scanf("%d",&S);
    144         if(cas<n)work1();//孤立点情况
    145         else spfa();//无孤立点情况
    146     }
    147     return 0;
    148 }
    149 /*
    150 //
    151 
    152 //
    153 */
    View Code
  • 相关阅读:
    16 把第 i 个结点从链表中删除
    15 在特定结点前插入新的元素
    14 求链表的表长
    13 返回特定数据域的结点个数
    12 按号定位
    11 按值定位
    11 头插入法创建链表)
    09 尾插入法创建单链表(实现2)
    08 尾插入法创建单链表(实现1)
    centos6.5 安装gcc 4.9.0
  • 原文地址:https://www.cnblogs.com/Coolxxx/p/5861772.html
Copyright © 2011-2022 走看看