UvaLive 4080 Warfare And Logistics

The army of United Nations launched a new wave of air strikes on terrorist forces. The objective of the mission is to reduce enemy’s logistical mobility. Each air strike will destroy a path and therefore increase the shipping cost of the shortest path between two enemy locations. The maximal damage is always desirable. Let’s assume that there are n enemy locations connected by m bidirectional paths, each with specific shipping cost. Enemy’s total shipping cost is given as
c =n ∑ i=1n ∑ j=1
path(i,j)
Here path(i,j) is the shortest path between locations i and j. In case i and j are not connected, path(i,j) = L. Each air strike can only destroy one path. The total shipping cost after the strike is noted as c′. In order to maximized the damage to the enemy, UN’s air force try to find the maximal c′−c.
Input The first line of each input case consists of three integers: n, m, and L. 1 < n ≤ 100, 1 ≤ m ≤ 1000, 1 ≤ L ≤ 108. Each of the following m lines contains three integers: a, b, s, indicating length of the path between a and b.
Output
For each case, output the total shipping cost before the air strike and the maximal total shipping cost after the strike. Output them in one line separated by a space.
Sample Input
4 6 1000 1 3 2 1 4 4 2 1 3 2 3 3 3 4 1 4 2 2
Sample Output
28 38

题目大意:

有一个n(1<n<=100)节点,m(1<m<=1000)条边的无向图,每条边上有一个正权

令 c 等于每队节点之间的最短路之和(如果节点不连通最短路的值为L)

现要删除一条边,使得新的 c 值最大

--------------------------------------------------------华丽的分割线----------------------------------------------------------------------------

解析:

我们可以先用dijkstra求出最短路树

找到n个节点之间最短路所用的n-1条边

再来考虑删除边

如果不是那n-1条边的其中之一

那么删除后 c 值不会发生该变

所以我们只用考虑删除那n-1条边其中一条的情况

时间复杂度为(n2m logn)

可以接受

代码如下:

  1 #include<queue>
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include<algorithm>
  5 using namespace std;
  6 #define N 3005
  7 #define LL long long
  8 int n,m,l;
  9 struct edge
 10 {
 11     int w,v,next;
 12 }e[N<<2];
 13 int head[N];
 14 int tot;
 15 int done[N];
 16 int vis[N<<2];
 17 LL sum[N][N<<2];
 18 LL dis[N];
 19 void add(int x,int y,int v)
 20 {
 21     e[tot].v=y;
 22     e[tot].w=v;
 23     e[tot].next=head[x];
 24     head[x]=tot++;
 25 }
 26 struct mypoint
 27 {
 28     int id,w,pre;
 29     bool operator <(const mypoint &a)const
 30     {
 31         return w>a.w;
 32     }
 33 }s,ss;
 34 LL dijkstra(int s,int f1,int f2)
 35 {
 36     priority_queue<mypoint>Q;
 37     memset(done,0,sizeof(done));
 38     for(int i=1;i<=n;i++)dis[i]=l;
 39     mypoint p;
 40     p.w=0,p.id=s,p.pre=-1;
 41     dis[s]=0;
 42     Q.push(p);
 43     while(!Q.empty())
 44     {
 45         p=Q.top();Q.pop();
 46         if(done[p.id])continue;
 47         done[p.id]=1;
 48         if(f1==tot&&f2==tot&&p.id!=s)
 49             vis[p.pre]=vis[p.pre^1]=1;
 50         for(int k=head[p.id];k!=-1;k=e[k].next)
 51         {
 52             if(k==f1||k==f2)continue;
 53             int u=p.id,v=e[k].v,len=e[k].w;
 54             if(dis[v]>dis[u]+len)
 55             {
 56                 dis[v]=dis[u]+len;
 57                 mypoint q;
 58                 q.id=v,q.w=dis[v],q.pre=k;
 59                 Q.push(q);
 60             }
 61         }
 62     }
 63     LL sum=0;
 64     for(int i=1;i<=n;i++)sum+=dis[i];
 65     return sum;
 66 }
 67 int main()
 68 {
 69     while(~scanf("%d%d%d",&n,&m,&l))
 70     {
 71         memset(head,-1,sizeof(head));
 72         tot=0;
 73         for(int i=0;i<m;i++)
 74         {
 75             int x,y,v;
 76             scanf("%d%d%d",&x,&y,&v);
 77             add(x,y,v);
 78             add(y,x,v);
 79         }
 80        /* for(int i=head[1];i;i=e[i].next)
 81         {
 82             printf("%d",e[i].v);
 83         }*/
 84       //  printf("%d",tot);
 85         for(int i=1;i<=n;i++)
 86         {
 87             memset(vis,0,sizeof(vis));
 88             sum[i][tot]=dijkstra(i,tot,tot);
 89             for(int j=0;j<tot;j++)
 90             {
 91                 if(vis[j]==0)sum[i][j]=sum[i][tot];
 92                 else sum[i][j]=dijkstra(i,j,j^1);
 93             }
 94         }
 95         LL ans1=0,ans2=0;
 96         for(int j=0;j<tot;j++)
 97         {
 98             LL cur=0;
 99             for(int i=1;i<=n;i++)
100             {
101                 cur+=sum[i][j];
102             }
103             ans2=max(ans2,cur);
104         }
105         for(int i=1;i<=n;i++)
106         {
107             ans1+=sum[i][tot];
108         }
109         printf("%lld %lld
",ans1,ans2);
110     }
111     return 0;
112 }
原文地址:https://www.cnblogs.com/xxjnoi/p/8384270.html