UVALive 4080 Warfare And Logistics
题意:给定一个n节点m条边的无向图,定义c为每对顶点的最短路之和,要求删掉一条边重新求一个c值c',求出c'最大值.
解法:dijkstra+堆优化,最短路径树.
首先可以通过dijkstra求出单源最短路,对于删边的操作,如果我们枚举每条边的时候都求一次最短路肯定是超时的.
对于一个源点确定的最短路径树,如果我们删掉的边不在这个最短路径树上,那么就不需要重新计算最短路.
根据这个性质,我们只需要记录下每个源点构成的最短路径树上都有哪条边,然后在枚举边的时候判断是否需要重新计算最短路
1 #include<cstdio> 2 #include<queue> 3 #include<iostream> 4 #include<cstring> 5 #include<algorithm> 6 #define N 3010 7 using namespace std; 8 typedef long long ll; 9 struct Edge{ 10 int u,v,len,next; 11 }edge[N]; 12 struct heap{ 13 int dis,id,pre; 14 bool operator < (const heap &a)const{ 15 return dis > a.dis; 16 } 17 }; 18 int head[N],cnt,dis[N],n,m,l; 19 bool used[N],hash[N]; 20 ll ans[N],sum[N][N]; 21 void init(){ 22 cnt=0; 23 memset(head,-1,sizeof(head)); 24 memset(hash,0,sizeof(hash)); 25 memset(ans,0,sizeof(ans)); 26 } 27 void addedge(int u,int v,int len){ 28 edge[cnt].u=u;edge[cnt].v=v; 29 edge[cnt].len=len; 30 edge[cnt].next=head[u]; 31 head[u]=cnt++; 32 } 33 ll dijkstra(int s,int f1,int f2){ 34 priority_queue<heap>Q; 35 memset(used,0,sizeof(used)); 36 for(int i=1;i<=n;i++)dis[i]=l; 37 heap p; 38 p.dis=0,p.id=s,p.pre=-1; 39 dis[s]=0; 40 Q.push(p); 41 while(!Q.empty()){ 42 p=Q.top();Q.pop(); 43 if(used[p.id])continue; 44 used[p.id]=1; 45 if(f1==cnt&&f2==cnt&&p.id!=s) 46 hash[p.pre]=hash[p.pre^1]=1; 47 for(int k=head[p.id];k!=-1;k=edge[k].next){ 48 if(k==f1||k==f2)continue; 49 int u=edge[k].u,v=edge[k].v,len=edge[k].len; 50 if(dis[v]>dis[u]+len){ 51 dis[v]=dis[u]+len; 52 heap q; 53 q.id=v,q.dis=dis[v],q.pre=k; 54 Q.push(q); 55 } 56 } 57 } 58 ll sum=0; 59 for(int i=1;i<=n;i++) 60 sum+=dis[i]; 61 return sum; 62 } 63 64 int main(){ 65 while(~scanf("%d%d%d",&n,&m,&l)){ 66 init(); 67 for(int i=0;i<m;i++){ 68 int a,b,c; 69 scanf("%d%d%d",&a,&b,&c); 70 addedge(a,b,c); 71 addedge(b,a,c); 72 } 73 for(int i=1;i<=n;i++){ 74 memset(hash,0,sizeof(hash)); 75 sum[i][cnt]=dijkstra(i,cnt,cnt); 76 for(int j=0;j<cnt;j++){ 77 if(hash[j]==0)sum[i][j]=sum[i][cnt]; 78 else sum[i][j]=dijkstra(i,j,j^1); 79 } 80 } 81 ll ans1=0,ans2=0; 82 for(int j=0;j<cnt;j++){ 83 ll all=0; 84 for(int i=1;i<=n;i++) 85 all+=sum[i][j]; 86 ans2=max(ans2,all); 87 } 88 for(int i=1;i<=n;i++){ 89 ans1+=sum[i][cnt]; 90 } 91 printf("%lld %lld\n",ans1,ans2); 92 } 93 return 0; 94 }