hdu 5876 Sparse Graph(补图最短路) 2016 ACM/ICPC Asia Regional Dalian Online 1009

2 篇文章 0 订阅

Sparse Graph

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


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
 

Source


题意:给一张图,求其补图的某源点的最短路。
由于点很多但是边很少所以不可以对其补图进行操作,建立原图,刚开始时和源点无边的点肯定补图中最短路径是1,并将这些点存入一个集合,下次再判断这这集合的点如果和其他的某个点如果没有一条边相连,这里用队列可以边记录边将集合中的点清空,则该点距离是2,并加入集合。。。接着继续该步骤直到集合空。

#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 200010;
vector<int> ans;
queue<int> que;
int result[maxn];
int flag[maxn];
bool vis[maxn];
int main()
{
    int t, n, m, s, step;
    scanf("%d", &t);
    while (t--)
    {
        ans.clear();
        memset(vis, false, sizeof(vis));
        while (!que.empty()) que.pop();
        scanf("%d%d", &n, &m);
        int x, y;
        vector<int> datas[maxn];
        for (int i = 0; i < m; ++i)
        {
            scanf("%d%d", &x, &y);
            datas[x].push_back(y);
            datas[y].push_back(x);
        }
        scanf("%d", &s);
        que.push(s);
        flag[s] = true;
        step = 0;
        int cnt = 0, tmp;
        while(!que.empty())
        {
            memset(flag, 0, sizeof(flag));
            ++step;
            tmp = que.front(); que.pop();
            cnt = 0;
            while(1)
            {
                cnt++;
                for (int i = 0; i < datas[tmp].size(); ++i) flag[datas[tmp][i]]++;
                if (!que.empty())
                {
                    tmp = que.front();
                    que.pop();
                }
                else
                {
                    break;
                }
            }
            for (int i = 1; i <= n; ++i)
            {
                if (cnt > flag[i])//表示i点不是和集合里所有点都相连,即补图中可以有一条边相连,在上个距离基础上加1即最短路
                {
                    if (!vis[i])
                    {
                        que.push(i);
                        vis[i] = true;
                        result[i] = step;
                    }
                }
            }
        }
        for (int i = 1; i <= n; ++i)
        {
            if (i != s)
            {
                if (vis[i])
                {
                    ans.push_back(result[i]);
                }
                else
                    ans.push_back(-1);
            }
        }
        int len = ans.size() - 1;
        for (int i = 0; i < len; ++i)
            printf("%d ", ans[i]);
        printf("%d\n", ans[len]);
    }
    return 0;
}




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值