zoukankan      html  css  js  c++  java
  • 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("
    ");
    127     FOR(i,1,n){
    128       v[i].clear();
    129     }
    130   }
    131   return 0;
    132 }
  • 相关阅读:
    HDU 5828 Rikka with Sequence (线段树+剪枝优化)
    Educational Codeforces Round 5 E. Sum of Remainders (思维题)
    HDU 2256 Problem of Precision (矩阵快速幂)
    Codeforces 597C. Subsequences (树状数组+dp)
    Codeforces Round #292 (Div. 1) B. Drazil and Tiles (类似拓扑)
    HDU 5794 A Simple Chess (Lucas + dp)
    Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum (离线树状数组+前缀xor)
    Codeforces Round #313 (Div. 2) E. Gerald and Giant Chess (Lucas + dp)
    进程内存空间的分布
    快排,堆排与归并排序
  • 原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/5860589.html
Copyright © 2011-2022 走看看