HDU5870 Alice's Adventure in Wonderland

news/2024/11/30 14:32:26/

   大概做法是这样的

      考虑最朴素的做法,预处理出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 }

 

转载于:https://www.cnblogs.com/fzmh/p/5861485.html


http://www.ppmy.cn/news/264152.html

相关文章

【JZOJ5870】地图

Description 给定N个度数为1或2的点&#xff0c;求所有带标号简单无向图&#xff08;无重边和自环&#xff09;的方案数。 Solution 设度数为2的点有 n n n个&#xff0c;度数为1的有 m m m个。 因为只有1和2&#xff0c;所以图一定是由许多链和大小大于等于3的简单环构成的…

RDA5870调试

时间&#xff1a;20100506 现象&#xff1a;我司准备在MTK6253上换蓝牙芯片为RDA5870. 调试过程&#xff1a; 1、首先将RDA5870给的相关代码放到我们自己的工程中&#xff0c;编译通过。但是在添加的时候要注意用相关的宏名控制。 首先在工程文件中添加&#xff1a; RDA_BLUETO…

mysqldump 逻辑备份的正确姿势

在上一篇文章 MySQL 命令行工具之 mysqldump 深入研究 中&#xff0c;我们搞定了mysqldump的参数和基本原理。那么我们该怎么样最好的使用它的&#xff1f;它有哪些坑呢&#xff1f; 1. 利用mysqldump进行逻辑备份 1&#xff09;全逻辑备份&#xff1a; mysqldump -uxxx -p --f…

AMD OpenCL 大学课程

AMD OpenCL大学课程是非常好的入门级OpenCL教程&#xff0c;通过看教程中的PPT&#xff0c;我们能够很快的了解OpenCL机制以及编程方法。下载地址&#xff1a;http://developer.amd.com/zones/OpenCLZone/universities/Pages/default.aspx 教程中的英文很简单&#xff0c;我相信…

【Linux】软硬链接

文章目录 制作软硬链接&#xff0c;对比差别提出软硬链接的应用场景总结 制作软硬链接&#xff0c;对比差别 制作软链接 1.先创建一个文件&#xff0c;并向其中写入内容&#xff1a; 2.建立软链接&#xff1a;ln -s myfile.txt my-soft 可以发现&#xff0c;软链接是一个独…

tp703n怎么做无线打印服务器,TP-Link TL-WR703N无线路由器无线AP模式怎么设置

TP-Link TL-WR703N无线路由器配置简单&#xff0c;不过对于没有网络基础的用户来说&#xff0c;完成路由器的安装和无线AP模式的设置&#xff0c;仍然有一定的困难&#xff0c;本文学习啦小编主要介绍TP-Link TL-WR703N无线路由器无线AP模式的设置方法! TP-Link TL-WR703N无线路…

TP-Link 886nV6 刷第三方系统回忆

886nV6刷第三方系统 886n普遍只有8m的闪存&#xff0c;刷不了大的第三方系统。因为手头没有闪存就没换&#xff0c;OpenWRT成了优先级最高的系统。相关的刷机教程可去相关论坛查看。 本人在tb购买CH341A编程器使用sop8夹具&#xff0c;夹住flash的引脚进行烧录。 刷机坑的提醒…

tlwr842n服务器无响应,TL-WR842n无线路由器掉线解决方法汇总

《TL-WR842n无线路由器掉线解决方法汇总》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《TL-WR842n无线路由器掉线解决方法汇总(1页珍藏版)》请在人人文库网上搜索。 1、TL-WR842n无线路由器掉线解决方法汇总用单机接宽带能正常上网的这一台电脑有线连接路由器的LAN口…