HDU2433Travel(SPFA+记录路径优化)

Travel

Time Limit: 10000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1847    Accepted Submission(s): 623

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

Source

2008 Asia Chengdu Regional Contest Online

题意:每次只能删除一条边,问每个点到所有点的最短路径总和最小。只要任意两个点之间没有路的就输出 INF。

#include<stdio.h>
#include<queue>
using namespace std;
const int N = 105;
const int inf = 99999999;
struct EDG
{
    int u,v,id;
};
vector<EDG>mapt[N];
int dis[N],n,numEdg[N][N],father[N],goEdg[N][N][N],sum[N];

void spfa(int id,int s,bool b)
{
    queue<int>q;
    int inq[N]={0};
    for(int i=1;i<=n;i++)
        dis[i]=inf;
    q.push(s);
    dis[s]=0; father[s]=s;
    while(!q.empty())
    {
        s=q.front(); q.pop();
        inq[s]=0;
        int len=mapt[s].size();
        for(int i=0;i<len;i++)
        if(id!=mapt[s][i].id)
        {
            int v=mapt[s][i].v;
            if(dis[v]>dis[s]+1)
            {
                dis[v]=dis[s]+1;
                if(b)
                 father[v]=s;
                if(inq[v]==0)
                    inq[v]=1,q.push(v);
            }
        }
    }
}
int main()
{
    int m,a,b;
    EDG ss,edg[N*30];
    while(scanf("%d%d",&n,&m)>0)
    {
        for(int i=1;i<=n;i++)
        {
            mapt[i].clear();
            for(int j=1;j<=n;j++)
            {
                numEdg[i][j]=0;
                for(int e=1;e<=n;e++)
                goEdg[i][j][e]=0;
            }
        }

        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&a,&b);
            edg[i].u=a; edg[i].v=b;
            numEdg[a][b]++; numEdg[b][a]++;
            if(numEdg[a][b]>1)
             continue;
            ss.id=i;
            ss.v=b; mapt[a].push_back(ss);
            ss.v=a; mapt[b].push_back(ss);
        }
        int SUM=0;
        for(int i=1;i<=n;i++)
        {
            spfa(-1,i,true);
            sum[i]=0;
            for(int j=1;j<=n;j++)
            if(dis[j]==inf)
            {
                sum[i]=inf; break;
            }
            else sum[i]+=dis[j];
            if(sum[i]==inf)
            {
               SUM=inf; break;
            }
            SUM+=sum[i];
            for(int j=1;j<=n;j++)
            {
                int u,v=j;
                while(father[v]!=v)
                {
                    u=father[v];
                    goEdg[i][u][v]=goEdg[i][v][u]=1;
                    v=u;
                }
            }
        }
        int ans;
        for(int id=1;id<=m;id++)
        {
            if(SUM==inf)
            {
                printf("INF\n"); continue;
            }
            else if(numEdg[edg[id].u][edg[id].v]>1)
            {
                printf("%d\n",SUM); continue;
            }
            ans=0;
            for(int i=1;i<=n;i++)
            if(goEdg[i][edg[id].u][edg[id].v])//最主要的优化
            {
                spfa(id,i,false);
                for(int j=1;j<=n;j++)
                 if(dis[j]==inf)
                {
                    ans=inf; break;
                }
                else ans+=dis[j];
                if(ans==inf)
                    break;
            }
            else ans+=sum[i];
            if(ans==inf)
                printf("INF\n");
            else printf("%d\n",ans);
        }
    }
}
时间: 2024-10-24 01:04:29

HDU2433Travel(SPFA+记录路径优化)的相关文章

zoj 3812 We Need Medicine (dp 位优化 巧妙记录路径)

We Need Medicine Time Limit: 10 Seconds      Memory Limit: 65536 KB      Special Judge A terrible disease broke out! The disease was caused by a new type of virus, which will lead to lethal lymphoedema symptom. For convenience, it was namedLL virus.

HDU 5137 How Many Maos Does the Guanxi Worth(floyd记录路径)

题意:给定N个点和M条边,点编号是1到N.现在要从2到N-1中选择一个删除,同时跟选择的点连接的边也就消失,然后使得点1到N的最短路径的长度最大.如果点1和点N不连通,则输出"Inf". 思路:直接暴力,枚举删去的点即可.我做了一步优化,只删原图最短路上的点, 所以用floyd的时候记录路径即可 //Accepted 1164 KB 0 ms #include<cstdio> #include<iostream> #include<cstring>

HDOJ 5294 Tricks Device 最短路(记录路径)+最小割

最短路记录路径,同时求出最短的路径上最少要有多少条边, 然后用在最短路上的边重新构图后求最小割. Tricks Device Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1584    Accepted Submission(s): 388 Problem Description Innocent Wu follows Dumb Z

[Python] 弗洛伊德(Floyd)算法求图的直径并记录路径

相关概念 对于一个图G=(V, E),求图中两点u, v间最短路径长度,称为图的最短路径问题.最短路径中最长的称为图的直径. 其中,求图中确定的某两点的最短路径算法,称为单源最短路径算法.求图中任意两点间的最短路径算法,称为多源最短路径算法. 常用的路径算法有: Dijkstra算法 SPFA算法\Bellman-Ford算法 Floyd算法\Floyd-Warshall算法 Johnson算法 其中最经典的是Dijkstra算法和Floyd算法.Floyd算法是多源最短路径算法,可以直接求出图

迪杰斯特拉--记录路径

迪杰斯特拉记录路径的办法就是开一个数组, 记录一下该节点的上一个节点是谁最后在递归输出就可以了 例题: B. wzy的大冒险——出发咯QAQ 单点时限: 2.0 sec 内存限制: 512 MB wzy踏上了冒险的旅程.现在他从地精手里买了一份地图,地图上有n个城镇.他从第一个城镇出发,走向(没钱只能走)第n个城镇,现在,请你帮wzy找到一条最短的路径,并倒序(从n到1)输出一条最短路径.举个栗子:如果有两条路径6 4 3 1和6 5 2 1,我们选择6 4 3 1这条.地精小提示:路是单向的Q

hdu 1226 BFS + bfs记录路径

http://acm.hdu.edu.cn/showproblem.php?pid=1226 为了省空间,可以用vis数组初始化的时候初始化为-1, 发现一个BFS容易错的地方 开始一直WA在这里:就是我int tp=q.front();之后马上q.pop():了,然后才去判断是不是符合条件以break,这样就不能根据q.empty()==1认为没有找到ans 因为这里WA了 其实也可以vis[0] == -1来判断 比较不理解的是 当n==0的时候 %n==0的时候怎么处理 //#pragma

poj 1166 The Clocks 记录路径的广搜

题意: 给9个时钟的初始状态,和一些对某几个钟的操作,求最少经过几步能到目标状态(全指向12点). 分析: 明显的广搜,但实现起来的细节要注意:1.因为要记录路径,所以要在整个程序执行过程中扩展出的节点在输出路径前不能销毁, 故采用静态内存分配的方法(开node[600000],用get_node()创建节点.2.queue<node>比queue<int>要多花1别的时间. //poj 1166 //sep9 #include <iostream> #include

URAL 1244 Gentlement DP +记录路径 好题

1244. Gentlemen Time limit: 0.5 secondMemory limit: 64 MB Let's remember one old joke: Once a gentleman said to another gentleman:— What if we play cards?— You know, I haven't played cards for ten years…— And I haven't played for fifteen years…So, li

POJ 1293 Duty Free Shop(背包记录路径)

Description Pedro travelled to Europe to take part in the International Olympiad in Informatics and is coming back home. Since all his friends asked him to bring them some gift, he bought two big bags of chocolates (one of Mindt and one of Lilka). Ea