您的位置:首页 > 其它

HDU 5876 Sparse Graph

2016-09-10 22:54 246 查看
题目:Sparse Graph

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

题意:给出一个图(V<=20万,E<=2万),要求先化为补图(每两个点,原本有边删去边,原本没边添加边),然后问指定点S到其他每个点的最短距离。

思路:

  普通的广搜应该解决不了。。。O(n*m)太大,不会很难,比赛时没做出来有点可惜,当知道过了也进不了时,就安慰了许多。

  变化一下思路,从起点出发,因为原本边<=2万,那么大部分的点都已经可以到达了,也就是len=1(len最短距离),现在用集合st 来存放还没到达的点,用ad[i]=true来表示i 已经到达,用co表示已经到达的点的数量。每一次循环遍历st,对于某一个还没到达的点x ,假定和x 相邻的点有m 个,如果m<co,那说明x 肯定能到达。因为原本y 和x 没有边,补图里肯定就有,也就是说最坏情况是m个点对应的都是已经遍历过的,那么co-m这些点肯定能到达x。如果m>=co,并不能说明x 一定到不了,现在就要遍历m个点,如果某个点是没有遍历过的,m可以-1,如果最终m<co,说明x 还是可以遍历到的。每一次循环,就是找出若干个x ,x能到达,如果没有这样的x 就可以退出了,如果有,集合删去这些x,记录len,记录ad,记录co ,进入下次循环。

  时间复杂度计算:集合最初最多2万个点,每次删掉就不恢复了,这里的时间为E,m>=co要找点时也就是遍历所有的边,每个边最多遍历1次,时间E。也就是说循环里看似套了很多层,其实很快,外面大概就是V,时间复杂度V+E。

AC代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<set>
#include<map>
#include<list>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
#define lson rt<<1
#define rson rt<<1|1
#define N 200010
#define M 100010
#define Mod 1000000007
#define LL long long
#define INF 0x7fffffff
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
#define For(i,f_start,f_end) for(int i=f_start;i<f_end;i++)
#define REP(i,f_end,f_start) for(int i=f_end;i>=f_start;i--)
#define Rep(i,f_end,f_start) for(int i=f_end;i>f_start;i--)
#define MT(x,i) memset(x,i,sizeof(x))
#define gcd(x,y) __gcd(x,y)
const double PI = acos(-1);

bool ad
;
int len
;
vector<int> v
;
vector<int> zan;
set<int> st;
int main()
{
int t,n,m,x,y;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
while(m--)
{
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
int s,co=1;
scanf("%d",&s);
st.clear();
MT(ad,0);
ad[s]=true;
For(i,0,v[s].size()){
ad[v[s][i]]=true;
}

MT(len,-1);
FOR(i,1,n){
if(i==s) continue;
if(ad[i]==false){
len[i]=1;
co++;
ad[i]=true;
}
else{
st.insert(i);
ad[i]=false;
}
}
int ll=2;
while(1)
{
zan.clear();
bool ff=false;
for(set<int>::iterator it=st.begin();it!=st.end();it++)
{
int x=*it;
bool flag=false;
if(v[x].size()<co)
{
flag=true;
}
else
{
int k=v[x].size();
For(i,0,v[x].size())
{
int son=v[x][i];
if(ad[son]==false) k--;
if(k<co) break;
}
if(k<co)
{
flag=true;
}
}
if(flag==true)
{
ff=true;
zan.push_back(x);
}
}
if(ff==false) break;
For(i,0,zan.size())
{
ad[zan[i]]=true;
len[zan[i]]=ll;
co++;
}
ll++;
for(set<int>::iterator it=st.begin();it!=st.end();)
{
int x=*it;
if(ad[x]==true) st.erase(it++);
else it++;
}
}
bool ff=false;
FOR(i,1,n){
if(i!=s){
if(ff!=false) printf(" ");
else ff=true;
printf("%d",len[i]);
}
}
printf("\n");
FOR(i,1,n){
v[i].clear();
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: