首页 > 代码库 > HDU 5876 Sparse Graph

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