Warfare And Logistics
题意:给n个点m条边。令c为每对节点的最短路长度之和。要求删除一条边后使得新的c值c‘最大,不连通的两点对短路视为L。
【如果每次删除一条边,要跑m次dijkstra,其实其中很多次都对最短路没有影响,因为删掉的边不在最短路里】
【因此,可以每次删除最短路树中的一条边,需要跑n次,复杂度降低到可接受程度】
1 #include <bits/stdc++.h> 2 #define LL long long 3 using namespace std; 4 const int inf=0x3f3f3f3f; 5 const int maxv=110; 6 const int maxe=2010; 7 int n,m,L; 8 struct Edge 9 { 10 int u,v,w; 11 int nex; 12 }e[maxe<<1]; 13 int head[maxv]; 14 int cnt=0; 15 void init() 16 { 17 memset(head,-1,sizeof(head)); 18 cnt=0; 19 } 20 void add(int u,int v,int w) 21 { 22 e[cnt].u=u; 23 e[cnt].v=v; 24 e[cnt].w=w; 25 e[cnt].nex=head[u]; 26 head[u]=cnt++; 27 } 28 29 typedef pair<int,int> PII; 30 int dis[maxv],par[maxv]; 31 void dijkstra(int s,bool c,int e1) 32 { 33 priority_queue<PII,vector<PII>,greater<PII> > pq; 34 for(int i=0;i<maxv;i++) dis[i]=L; 35 dis[s]=0; 36 pq.push(PII(0,s)); 37 par[s]=-1; 38 while(!pq.empty()) 39 { 40 PII t=pq.top(); 41 pq.pop(); 42 int u=t.second; 43 if(dis[u]<t.first) continue; 44 for(int i=head[u];i!=-1;i=e[i].nex) 45 { 46 if(i==e1||i==(e1^1)) continue; // 47 int v=e[i].v; 48 if(dis[v]>dis[u]+e[i].w) 49 { 50 dis[v]=dis[u]+e[i].w; 51 if(c) par[v]=i; 52 pq.push(PII(dis[v],v)); 53 } 54 } 55 } 56 } 57 LL cal() 58 { 59 LL temp=0; 60 for(int i=0;i<n;i++) 61 temp+=dis[i]; 62 return temp; 63 } 64 vector<int> vv; 65 int delta[maxe]; 66 67 int main() 68 { 69 while(scanf("%d%d%d",&n,&m,&L)!=EOF) 70 { 71 init(); 72 int u,v,w; 73 for(int i=0;i<m;i++) 74 { 75 scanf("%d%d%d",&u,&v,&w); 76 u--;v--; 77 add(u,v,w); 78 add(v,u,w); 79 } 80 LL ans=0; 81 vv.clear(); 82 memset(delta,0,sizeof(delta)); 83 for(int i=0;i<n;i++) 84 { 85 dijkstra(i,1,-1); 86 LL temp=cal(); 87 ans+=temp; 88 for(int j=0;j<n;j++) 89 if(par[j]!=-1) 90 { 91 dijkstra(i,0,par[j]); 92 int id=par[j]&(~1); // 93 if(!delta[id]) vv.push_back(id); 94 delta[id]+=cal()-temp; 95 } 96 97 } 98 int maxdelta=0; 99 for(int i=0;i<(int)vv.size();i++) 100 maxdelta=max(maxdelta,delta[vv[i]]); 101 printf("%lld %lld ",ans,ans+maxdelta); 102 } 103 }