1. 程式人生 > >HDU 5876 最短路+補圖

HDU 5876 最短路+補圖

題目

Sparse Graph

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


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 n
ot
 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 N
1
 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

題意

  輸入的是一個圖,但是我們要求的是補圖,補圖就是整個圖減去我們輸入的圖,這裡是百度百科 https://baike.baidu.com/item/%E8%A1%A5%E5%9B%BE?fr=aladdin。

 我先知道了一個點S,求的就是S在這個補圖中,到其他個點的最短路,如果不存在就輸出-1

解題思路

這個題的關鍵在於怎麼去處理補圖,求最短路對我們來說不是什麼大問題,那怎麼處理補圖呢,我們開一個數組link,裡面存當前點可以到達的點,再開一個數組inlink存當前點不能到達的點,初始化link的時候把除了自己本身的點我們都加上,無法到達的我們先一個也不存,然後假設我們在起點S,那麼根據輸入,我們就能找到S無法到達的點,我們把該點從link裡面刪除,把他加入到inlink,這樣子我們計算最短路,只要找link陣列就好了,而且這些點到S就是d[s]+1,這裡有一個巧妙的計算就是,因為我們是從起點S開始的,如果我們已經找到這個點了我們就不需要再找一次(也就是再加入一次link陣列)了,因為他已經是最短路了,需要加入link陣列的只有我們還沒有找到的點,而我們還沒找到的點都在inlink裡面,處理完之後交換一下就好了,具體的看程式碼吧

程式碼裡面用的Set,因為方便插入和刪除而且是唯一的,就像圖中的點一樣每個點也是唯一的。

#include<set>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=200000+6;
int n,m;
int d[maxn];
vector<int>e[maxn];
void dfs(int s)
{
    memset(d,0,sizeof(d));
    set<int>link,inlink;
    for(int i=1;i<=n;i++)
    {
        if(i!=s)
            link.insert(i);
    }
    queue<int> q ;
    q.push(s);
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        for(auto &y:e[x])
        {
            if(!link.count(y))
                continue;
            link.erase(y);
            inlink.insert(y);
        }
        for(auto &y:link)
        {
            d[y]=d[x]+1;
            q.push(y);
        }
        link.swap(inlink);
        inlink.clear();
    }
    int flag=0;
    for(int i=1;i<=n;i++)
    {
        if(i!=s)
        {
            if(flag)
            {
                printf(" ");
            }
            if(!d[i])
                printf("-1");
            else
                printf("%d",d[i]);
            flag=1;
        }
    }
    printf("\n");
}
void work()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        e[i].clear();
    int u,v;
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&u,&v);
        e[u].push_back(v);
        e[v].push_back(u);
    }
    int s;
    scanf("%d",&s);
    dfs(s);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        work();
    }
    return 0;
}