单源最短路(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\n");
                continue;
            }
            sum_v=0;
            spfa(y[i]);
            for(j=1;j<=n;j++)
                sum_v+=dis[j];
            printf("%d\n",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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值