Sparse Graph(HDU 5876)

大连网络赛的倒数第二题,比赛时想的太多了,没有A掉,挺可惜的!以下是题目

Sparse Graph

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


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

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

题目的意思就是给你一个图与及一个起点,再根据给出的图找出这个图完全图的补图,最后求出补图上除起点外每个点到起点的距离(以为边没有权值,距离为起点到该点的最小边数)。

解题思路:
首先储存一下刚开始时图的边,而这些边在补图上不会存在,如果没有储存的边都是补图上的边, 这样就可以做出了补图。然后在补图上找出距离从1到n-1的点(因为一个图上两点之间的最长距离为n-1),找不到就无法到达起点,距离用一个数组储存。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int big = 2e5 + 7;
const int INF = 0x7f7f7f7f;
vector<int>z[big];
int dis[big], n, m, k, record[big], num1, num2;
int fuck[big], sum, mid[big], amout;
bool vis[big];
void initialization()
{
    for(int i = 1; i <= n; i ++)
    {
        dis[i] = -1;
        z[i].clear();
    }
}
bool judge(int key)
{
    int temp = 0;
    for(int i = 0, j = z[key].size(); i < j; i ++)
        if(vis[z[key][i]]) temp ++;
    return temp < num2;
}
void bfs()
{
    bool flag;
    for(int i = 1, d; i < n; i ++)
    {
        flag = true;
        sum = 0;
        for(int j = 1; j <= num1; j ++)
        {
            d = record[j];
            if(!judge(d)) continue;
            flag = false;
            fuck[++ sum] = d;
            record[j] = 0;
        }
        if(flag) return; /// 此处是优化,因为当距离为i时,没有点能到达,距离大于i的点不存在!
        for(int j = 1; j <= sum; j ++)
        {
            d = fuck[j];
            vis[d] = true;
            dis[d] = i;
        }
        amout = 0;
        for(int j = 1; j <= num1; j ++)
        {
            if(!record[j]) continue;
            mid[++ amout] = record[j];
        }
        for(int j = 1; j <= amout; j ++)
            record[j] = mid[j];
        num1 -= sum;
        num2 += sum;
    }
}
int main()
{
    int t, u, v;
    scanf("%d", &t);
    while(t --)
    {
        scanf("%d %d", &n, &m);
        initialization();
        for(int i = 1; i <= m; i ++)
        {
            scanf("%d %d", &u, &v);
            z[u].push_back(v);
            z[v].push_back(u);
        }
        scanf("%d", &k);
        memset( vis, false, sizeof( vis));
        num1 = 0;
        for(int i = 1; i <= n; i ++)
        {
            if(i == k) continue;
            record[++ num1] = i;
        }
        num2 = n - num1;
        dis[k] = 0;
        vis[k] = true;
        bfs();
        for(int i = 1, s = 0; i <= n; i ++)
        {
            if(!dis[i]) continue;
            if(s ++) printf(" ");
            printf("%d", dis[i]);
        }
        printf("\n");
    }
    return 0;
}


 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值