HDU 5876 Sparse Graph
Posted hchlqlz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5876 Sparse Graph相关的知识,希望对你有一定的参考价值。
题目: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代码:
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<math.h> 5 #include<set> 6 #include<map> 7 #include<list> 8 #include<stack> 9 #include<queue> 10 #include<vector> 11 #include<string> 12 #include<iostream> 13 #include<algorithm> 14 using namespace std; 15 #define lson rt<<1 16 #define rson rt<<1|1 17 #define N 200010 18 #define M 100010 19 #define Mod 1000000007 20 #define LL long long 21 #define INF 0x7fffffff 22 #define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++) 23 #define For(i,f_start,f_end) for(int i=f_start;i<f_end;i++) 24 #define REP(i,f_end,f_start) for(int i=f_end;i>=f_start;i--) 25 #define Rep(i,f_end,f_start) for(int i=f_end;i>f_start;i--) 26 #define MT(x,i) memset(x,i,sizeof(x)) 27 #define gcd(x,y) __gcd(x,y) 28 const double PI = acos(-1); 29 30 bool ad[N]; 31 int len[N]; 32 vector<int> v[N]; 33 vector<int> zan; 34 set<int> st; 35 int main() 36 { 37 int t,n,m,x,y; 38 scanf("%d",&t); 39 while(t--) 40 { 41 scanf("%d%d",&n,&m); 42 while(m--) 43 { 44 scanf("%d%d",&x,&y); 45 v[x].push_back(y); 46 v[y].push_back(x); 47 } 48 int s,co=1; 49 scanf("%d",&s); 50 st.clear(); 51 MT(ad,0); 52 ad[s]=true; 53 For(i,0,v[s].size()){ 54 ad[v[s][i]]=true; 55 } 56 57 MT(len,-1); 58 FOR(i,1,n){ 59 if(i==s) continue; 60 if(ad[i]==false){ 61 len[i]=1; 62 co++; 63 ad[i]=true; 64 } 65 else{ 66 st.insert(i); 67 ad[i]=false; 68 } 69 } 70 int ll=2; 71 while(1) 72 { 73 zan.clear(); 74 bool ff=false; 75 for(set<int>::iterator it=st.begin();it!=st.end();it++) 76 { 77 int x=*it; 78 bool flag=false; 79 if(v[x].size()<co) 80 { 81 flag=true; 82 } 83 else 84 { 85 int k=v[x].size(); 86 For(i,0,v[x].size()) 87 { 88 int son=v[x][i]; 89 if(ad[son]==false) k--; 90 if(k<co) break; 91 } 92 if(k<co) 93 { 94 flag=true; 95 } 96 } 97 if(flag==true) 98 { 99 ff=true; 100 zan.push_back(x); 101 } 102 } 103 if(ff==false) break; 104 For(i,0,zan.size()) 105 { 106 ad[zan[i]]=true; 107 len[zan[i]]=ll; 108 co++; 109 } 110 ll++; 111 for(set<int>::iterator it=st.begin();it!=st.end();) 112 { 113 int x=*it; 114 if(ad[x]==true) st.erase(it++); 115 else it++; 116 } 117 } 118 bool ff=false; 119 FOR(i,1,n){ 120 if(i!=s){ 121 if(ff!=false) printf(" "); 122 else ff=true; 123 printf("%d",len[i]); 124 } 125 } 126 printf("\n"); 127 FOR(i,1,n){ 128 v[i].clear(); 129 } 130 } 131 return 0; 132 }
以上是关于HDU 5876 Sparse Graph的主要内容,如果未能解决你的问题,请参考以下文章