首页 > 代码库 > HDU5870 Alice's Adventure in Wonderland

HDU5870 Alice's Adventure in Wonderland

   大概做法是这样的

      考虑最朴素的做法,预处理出1到所有点的最短路数组dis1和方案数数组cnt1,和预处理出n到所有点的最短路数组dis2和方案数数组出cnt2,然后暴力枚举点对(A,B),如果A和B之间没有连边,那么就可以考虑添加一条正权边,满足这个条件就能添加dis1[A]+dis2[B]+1<=dis1[n],且cnt1[A]*cnt2[B]>=X,由于是要使方案增加,所以将边权设为dis1[n]-(dis1[A]+dis2[B])是最好的,因为可以继承原有的最短路方案数。那么由于(A,B)和(B,A)只算一次,那么第一维枚举到A第二维枚举到B,和第一维枚举到B第二维枚举到A会不会算同一种呢,可以证明这种情况并不会出现重复技计数。

       那么考虑优化,枚举点A,点B需满足dis1[A]+dis2[B]+1<=dis1[n],那么可以将dis2进行排序,然后二分出临界范围,然后查询出这个范围内cnt2[B]>=X/cnt[A]的数目,离线的话做法估计挺多的,我代码里用了主席树,最后还需要去掉范围内已经连边的点和自身。时间复杂度O(nlogn)

 

  代码

  1 #include<cstdio>  2 #include<vector>  3 #include<set>  4 #include<queue>  5 #include<algorithm>  6 #define mp make_pair  7 #define pb push_back  8 #define fi first  9 #define sc second 10 using namespace std; 11 const int N = 201010; 12 const int M = 2010101; 13 const int inf = 2100000000; 14 typedef pair<int,int> P;  15 priority_queue<P,vector<P>,greater<P> > Q; 16 int n,m,i,a,b,c,dis[N],cnt[N],dis1[N],cnt1[N],dis2[N],cnt2[N],X; 17 int id[N],ID[N],Id[N]; 18 vector<P> e[N]; 19 void gao(int x) 20 { 21     int i; 22     for (i=1;i<=n;i++) 23     dis[i]=inf,cnt[i]=0; 24     dis[x]=0; 25     cnt[x]=1; 26     Q.push(mp(0,x)); 27     while (!Q.empty()) 28     { 29         P tmp=Q.top(); 30         Q.pop(); 31         x=tmp.sc; 32         if (dis[x]!=tmp.fi) continue; 33         for (i=0;i<e[x].size();i++) 34         if (dis[x]+e[x][i].sc<dis[e[x][i].fi]) 35         { 36             dis[e[x][i].fi]=dis[x]+e[x][i].sc; 37             cnt[e[x][i].fi]=cnt[x]; 38             Q.push(mp(dis[e[x][i].fi],e[x][i].fi)); 39         } 40         else 41         if (dis[x]+e[x][i].sc==dis[e[x][i].fi]) 42         { 43             cnt[e[x][i].fi]+=cnt[x]; 44             if (cnt[e[x][i].fi]>X) cnt[e[x][i].fi]=X; 45         } 46     } 47 } 48  49 int ls[M],rs[M],s[M],tot,root[N]; 50 void build(int &x,int a,int b) 51 { 52     x=++tot; 53     ls[x]=rs[x]=s[x]=0; 54     if (b-a>1) 55     { 56         int m=(a+b)>>1; 57         build(ls[x],a,m); 58         build(rs[x],m,b); 59     } 60 } 61 void insert(int y,int &x,int a,int b,int l,int r) 62 { 63     x=++tot; 64     ls[x]=ls[y];rs[x]=rs[y];s[x]=s[y]+1; 65     if ((a<=l)&&(r<=b)) 66     return; 67     int m=(l+r)>>1; 68     if (a<m) insert(ls[y],ls[x],a,b,l,m); 69     if (m<b) insert(rs[y],rs[x],a,b,m,r); 70 } 71 int query(int x,int a,int b,int l,int r) 72 { 73     if ((a<=l)&&(r<=b)) 74     return s[x]; 75     int m=(l+r)>>1,ans=0; 76     if (a<m) ans+=query(ls[x],a,b,l,m); 77     if (m<b) ans+=query(rs[x],a,b,m,r); 78     return ans; 79 } 80 bool cmp(int a,int b) 81 { 82     return dis2[a]<dis2[b]; 83 } 84 bool CMP(int a,int b) 85 { 86     return cnt2[a]>cnt2[b]; 87 } 88 int main() 89 { 90     while (~scanf("%d%d",&n,&m)) 91     { 92     if (n+m==0) return 0; 93     for (i=1;i<=n;i++) e[i].clear(); 94     scanf("%d",&X); 95     for (i=1;i<=m;i++) 96     { 97         scanf("%d%d%d",&a,&b,&c); 98         e[a].pb(mp(b,c)); 99         e[b].pb(mp(a,c));100     }101     gao(1);102     for (i=1;i<=n;i++)103     dis1[i]=dis[i],cnt1[i]=cnt[i];104     gao(n);105     for (i=1;i<=n;i++)106     dis2[i]=dis[i],cnt2[i]=cnt[i];107     108     tot=0;109     build(root[0],0,n);110     for (i=1;i<=n;i++)111     id[i]=i;112     sort(id+1,id+1+n,cmp);113     for (i=1;i<=n;i++)114     ID[id[i]]=i;115     116     for (i=1;i<=n;i++)117     Id[i]=i;118     sort(Id+1,Id+1+n,CMP);119     for (i=1;i<=n;i++)120         insert(root[i-1],root[i],ID[Id[i]]-1,ID[Id[i]],0,n);121     long long ans=0;122     for (i=1;i<=n;i++)123     {124         int l=1,r=n;125         while (l<=r)126         {127             m=(l+r)>>1;128             if (dis2[id[m]]+dis1[i]+1<=dis1[n]) l=m+1;else r=m-1;129         }130         int j=r;131 132         l=1;r=n;133         while (l<=r)134         {135             m=(l+r)>>1;136             if (1LL*cnt1[i]*cnt2[Id[m]]>=X) l=m+1;else r=m-1;137         }138         139         if (j) ans=ans+query(root[r],0,j,0,n);140         141         142         for (int k=0;k<e[i].size();k++)143         if (dis2[e[i][k].fi]+1+dis1[i]<=dis1[n])144         if (1LL*cnt1[i]*cnt2[e[i][k].fi]>=X) ans--;145     146         if (dis1[i]+dis2[i]+1<=dis1[N])147         if (1LL*cnt1[i]*cnt2[i]>=X) ans--;148         149     }150     printf("%lld\n",ans);151     }152 }

 

HDU5870 Alice's Adventure in Wonderland