HDU 5876 最短路+補圖
阿新 • • 發佈:2019-02-19
題目
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
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
Output For each of T test cases, print a single line consisting of N
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;
}