【UVA1416】(LA4080) Warfare And Logistics (单源最短路)

题目:

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个节点m条无向边的图,每条边权都为正。令c等于每对结点的最短路长度之和。要求删一条边后使得新的c值c‘最大。不连通两点的最短路长度视为L。(1<=n<=100,1<=m<=1000,1<=L<=10^8)

 

分析:

  因为规模比较小,所以可以考虑删边。主要是删什么边的问题。

  这里用到最短路树。在源点确定的情况下,只要最短路树不被破坏,起点到所有点的距离都不会改变。所以对于一个点,只有删掉最短路树上的边,我们才要重新做一次单源最短路。时间复杂度是O(n^2mlogn)。

 

代码如下:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 using namespace std;
  8 #define Maxn 110
  9 #define Maxm 1100
 10 #define INF 100000000
 11 
 12 struct node
 13 {
 14     int x,y,c,next;
 15     int ans;
 16     bool p;
 17 }t[Maxm*2];int len;
 18 
 19 int first[Maxn],dis[Maxn];
 20 bool inq[Maxn];
 21 bool hp[Maxn];
 22 queue<int > q;
 23 int n,m,L;
 24 
 25 void ins(int x,int y,int c)
 26 {
 27     t[++len].x=x;t[len].y=y;t[len].c=c;t[len].ans=0;
 28     t[len].next=first[x];first[x]=len;
 29 }
 30 
 31 int mymax(int x,int y) {return x>y?x:y;}
 32 
 33 void spfa(int s,int l)
 34 {
 35     if(!q.empty()) q.pop();
 36     memset(inq,0,sizeof(inq));
 37     memset(dis,63,sizeof(dis));
 38     memset(hp,0,sizeof(hp));
 39     q.push(s);dis[s]=0;hp[s]=1;inq[s]=1;
 40     while(!q.empty())
 41     {
 42         int x=q.front();inq[x]=0;q.pop();
 43         for(int i=first[x];i;i=t[i].next)
 44         {
 45             if(i==l) continue;
 46             if(i==(l%2==0?l-1:l+1)) continue;
 47             int y=t[i].y;hp[y]=1;
 48             if(dis[y]>dis[x]+t[i].c)
 49             {
 50                 dis[y]=dis[x]+t[i].c;
 51                 if(!inq[y])
 52                 {
 53                     q.push(y);
 54                     inq[y]=1;
 55                 }
 56             }
 57         }
 58     }
 59 }
 60 
 61 int ffind(int s)
 62 {
 63     int now=0;
 64     for(int i=1;i<=n;i++) if(i!=s)
 65     {
 66         if(hp[i]) now+=dis[i];
 67         else now+=L;
 68     }
 69     return now;
 70 }
 71 
 72 int main()
 73 {
 74     while(scanf("%d%d%d",&n,&m,&L)!=EOF)
 75     {
 76         memset(first,0,sizeof(first));
 77         len=0;
 78         for(int i=1;i<=m;i++)
 79         {
 80             int x,y,c;
 81             scanf("%d%d%d",&x,&y,&c);
 82             ins(x,y,c);ins(y,x,c);
 83         }
 84         int ft=0;
 85         for(int i=1;i<=n;i++)
 86         {
 87             spfa(i,0);int now=ffind(i);
 88             ft+=now;
 89             for(int j=1;j<=len;j++) t[j].p=0;
 90             for(int j=1;j<=len;j++)
 91             {
 92                 if(dis[t[j].x]==dis[t[j].y]+t[j].c) t[j].p=t[j%2==0?j-1:j+1].p=1;
 93             }
 94             for(int j=1;j<=len;j++) 
 95             if(t[j].p)
 96             {
 97                 spfa(i,j);
 98                 t[j].ans+=ffind(i);
 99             }
100             else t[j].ans+=now;
101         }
102         int mx=ft;
103         for(int i=1;i<=len;i++) mx=mymax(mx,t[i].ans);
104         printf("%d %d\n",ft,mx);
105     }
106     return 0;
107 }
[UVA1416]

 

2016-04-05 14:04:01

posted @ 2016-04-05 14:02  konjak魔芋  阅读(226)  评论(0编辑  收藏  举报