单源最短路(spfa),删边求和

http://acm.hdu.edu.cn/showproblem.php?pid=2433

Travel

Time Limit: 10000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1572    Accepted Submission(s): 526


Problem Description
      One day, Tom traveled to a country named BGM. BGM is a small country, but there are N (N <= 100) towns in it. Each town products one kind of food, the food will be transported to all the towns. In addition, the trucks will always take the shortest way. There are M (M <= 3000) two-way roads connecting the towns, and the length of the road is 1.
      Let SUM be the total distance of the shortest paths between all pairs of the towns. Please write a program to calculate the new SUM after one of the M roads is destroyed.

 

Input
      The input contains several test cases.
      The first line contains two positive integers N, M. The following M lines each contains two integers u, v, meaning there is a two-way road between town u and v. The roads are numbered from 1 to M according to the order of the input.
      The input will be terminated by EOF.

 

Output
      Output M lines, the i-th line is the new SUM after the i-th road is destroyed. If the towns are not connected after the i-th road is destroyed, please output “INF” in the i-th line. 
 

Sample Input
5 4 5 1 1 3 3 2 5 4 2 2 1 2 1 2
 

Sample Output
INF INF INF INF 2 2
 
题意:

因为每次只删除一条边,所以删除边后的sum,其实就与这条边上有关,或者所是和这条边上的两个端点有关,
首先 每次删除边都计算一次的暴力做法是不可能ac的, 除了用什么优化,但是也是很慢的。
所以只能在每次删除边的时候,做一些改变。
具体的做法是:
对每一个点求一次最短路,并将其求和,保存在一个数组里头,定为sum[i],i表示着一个点到所有其他点最短路之和。并将这些和相加 ans = sum[1]  + …… + sum[n]; 
      然后,删除一条边,其顶点暂定为u,v,对这条边的一个顶点u在一次求最短路,如果这个点,不能到达这条边的另一个点v,则 直接输出INF
      如果,能够到达,则对v也求一次最短路,对于u,v两点来说,求得u到每一个点的最短路之和sum_u,求得v到每一个点的最短路之和sum_v,
      最后结果为: ans = ans + sum_u + sum_v - sum[u] - sum[v];
程序:
#include"stdio.h"
#include"string.h"
#include"queue"
#include"iostream"
#define inf 10000
#define M 111
using namespace std;
int n,dis[M],use[M];
struct st
{
    int u,v,w,next;
}edge[M*M];
int head[M],t;
void init()
{
    t=0;
    memset(head,-1,sizeof(head));
}
void add(int u,int v,int w)
{
    edge[t].u=u;
    edge[t].v=v;
    edge[t].w=w;
    edge[t].next=head[u];
    head[u]=t++;
}
void spfa(int s)
{
    int i;
    queue<int>q;
    memset(use,0,sizeof(use));
    for(i=1;i<=n;i++)
        dis[i]=inf;
    dis[s]=0;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        use[u]=0;
        for(i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].v;
            if(dis[v]>dis[u]+edge[i].w)
            {
                dis[v]=dis[u]+edge[i].w;
                if(!use[v])
                {
                    use[v]=1;
                    q.push(v);
                }
            }
        }
    }
}
int x[3009],y[3009],sum[M];
int main()
{
    int m,i,j,sum_v,sum_u;
    while(scanf("%d%d",&n,&m)!=-1)
    {
        init();
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&x[i],&y[i]);
            add(x[i],y[i],1);
            add(y[i],x[i],1);
        }
        int ans=0;
        for(i=1;i<=n;i++)
        {
            sum[i]=0;
            spfa(i);
            for(j=1;j<=n;j++)
                sum[i]+=dis[j];
            ans+=sum[i];
        }
        for(i=1;i<=m;i++)
        {
            edge[i*2-1].w=edge[i*2-2].w=inf;
            spfa(x[i]);
            sum_u=0;
            for(j=1;j<=n;j++)
                sum_u+=dis[j];
            if(sum_u>=inf)
            {
                edge[i*2-1].w=edge[i*2-2].w=1;
                printf("INF
");
                continue;
            }
            sum_v=0;
            spfa(y[i]);
            for(j=1;j<=n;j++)
                sum_v+=dis[j];
            printf("%d
",ans+sum_u+sum_v-sum[x[i]]-sum[y[i]]);
            edge[i*2-1].w=edge[i*2-2].w=1;
        }
    }
}



原文地址:https://www.cnblogs.com/mypsq/p/4348218.html