hdu2433 spfa+mark[x][u][v]优化
题意:
删除每一条边求最短路的和,每删除一个就输出一个和.
思路:
直接暴力可定TLE了,自己SB的尝试过,就要剪纸,当每次输出一个答案的时候我们没有必要再从新暴力全跑一边最短路,我们可以开一个数组mark[s][u][v]来标记,当s为起点是边u,v是否被用过(其实是可能,记录的时候是更新就假设被用过,但也能达到剪纸的目的),开个sum[i]数组记录已i为起点时的和,如果被用过那么以s为起点的就得从新跑,否则不用(跑sum[s]也不会变化,所以没必要跑).这样能节省很多时间,但自己想想,如果管理员精心设计各种数据,让你每一条边都可能被用过那么就TLE了,但估计不会那么变态,卡数据可以,不能变态的卡,不然题目的答案岂不是要唯一化了..
#include<stdio.h>
#include<string.h>
#include<queue>
#define N_node 105
#define N_edge 6100
#define inf 1000000000
using namespace std;
typedef struct
{
int to ,cost ,next;
}STAR;
STAR E[N_edge];
int list[N_node] ,tot;
int s_x[N_node];
int mark[N_node][N_node][N_node];
int map[N_node][N_node];
int sum[N_node];
int Q[N_edge>>1][2];
void add(int a ,int b ,int c)
{
E[++tot].to = b;
E[tot].cost = c;
E[tot].next = list[a];
list[a] = tot;
}
void spfa(int s ,int n ,int key ,int u ,int v)
{
int mark_q[N_node] = {0};
mark_q[s] = 1;
for(int i = 0 ;i <= n ;i ++)
s_x[i] = inf;
s_x[s] = 0;
queue<int>q;
q.push(s);
while(!q.empty())
{
int xin ,tou;
tou = q.front();
q.pop();
mark_q[tou] = 0;
for(int k = list[tou] ;k ;k = E[k].next)
{
xin = E[k].to;
if(u == tou && v == xin || u == xin && v == tou)
continue;
if(s_x[xin] > s_x[tou] + E[k].cost)
{
s_x[xin] = s_x[tou] + E[k].cost;
if(key == 1)
mark[s][tou][xin] = mark[s][xin][tou] = 1;
if(!mark_q[xin])
{
mark_q[xin] = 1;
q.push(xin);
}
}
}
}
return ;
}
int main ()
{
int n ,m ,i ,a ,b ,ii ,jj;
while(~scanf("%d %d" ,&n ,&m))
{
memset(list ,0 ,sizeof(list));
memset(map ,0 ,sizeof(map));
tot = 1;
for(i = 1 ;i <= m ;i ++)
{
scanf("%d %d" ,&a ,&b);
map[a][b] ++;
map[b][a] ++;
add(a ,b ,1);
add(b ,a ,1);
Q[i][0] = a;
Q[i][1] = b;
}
int first = 0;
memset(sum ,0 ,sizeof(sum));
memset(mark ,0 ,sizeof(mark));
for(i = 1 ;i <= n ;i ++)
{
spfa(i ,n ,1 ,0 ,0);
for(ii = 1 ;ii <= n ;ii ++)
{
sum[i] += s_x[ii];
if(s_x[ii] == inf)
break;
}
first += sum[i];
if(ii != n + 1)
break;
}
if(i != n + 1)
{
for(i = 1 ;i <= m ;i ++)
printf("INF\n");
continue;
}
for(i = 1 ;i <= m ;i ++)
{
a = Q[i][0];
b = Q[i][1];
if(map[a][b] > 1)
{
printf("%d\n" ,first);
continue;
}
int now = first;
int kk = 0;
for(ii = 1 ;ii <= n ;ii ++)
{
if(mark[ii][a][b])
{
spfa(ii ,n ,0 ,a ,b);
int s = 0;
for(jj = 1 ;jj <= n ;jj ++)
{
s += s_x[jj];
if(s_x[jj] == inf)
break;
}
now = now - sum[ii] + s;
if(jj != n + 1)
break;
}
}
if(ii != n + 1)
{
printf("INF\n");
continue;
}
printf("%d\n" ,now);
}
}
return 0;
}
hdu2433 spfa+mark[x][u][v]优化的更多相关文章
- 关于SPFA的双端队列优化
7.11 Update 我做题的时候发现这样写会RE 因为在使用双端队列优化SPFA的时候 在将一个点加入队列的时候,如果队列已经空了 那么一旦出现dis[Q.front()]就会RE 可以这样修改 ...
- POJ——3159Candies(差分约束SPFA+前向星+各种优化)
Candies Time Limit: 1500MS Memory Limit: 131072K Total Submissions: 28071 Accepted: 7751 Descrip ...
- spfa + slf优化
最近在练习费用流 , 不是要用spfa吗 ,我们教练说:ns学生写朴素的spfa说出去都让人笑 . QwQ,所以就去学了一下优化 . slf优化就是双向队列优化一下,本来想用lll优化,可是优化后我t ...
- Codeforces 938D Buy a Ticket 【spfa优化】
用到了网络流的思想(大概).新建一个源点s,所有边权扩大两倍,然后所有的点向s连边权为点权的无向边,然后以s为起点跑spfa(S什么L优化的),这样每个点到s的距离就是答案. 原因的话,考虑答案应该是 ...
- hdu 1874(最短路 Dilkstra +优先队列优化+spfa)
畅通工程续 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- SPFA 的两个优化
From NOCOW SPFA算法有两个优化算法 SLF 和 LLL: SLF:Small Label First 策略,设要加入的节点是j,队首元素为i,若dist(j)<dist(i),则将 ...
- 【最短路径】 SPFA算法优化
首先先明确一个问题,SPFA是什么?(不会看什么看,一边学去,传送门),SPFA是bellman-ford的队列优化版本,只有在国内才流行SPFA这个名字,大多数人就只知道SPFA就是一个顶尖的高效算 ...
- 队列优化dijsktra(SPFA)的玄学优化
转载:大佬博客 最近想到了许多优化spfa的方法,这里想写个日报与大家探讨下 前置知识:spfa(不带任何优化) 由于使用较多 STLSTL ,本文中所有代码的评测均开启 O_2O2 优化 对一些数 ...
- SPFA的两个(卡时)优化
SPFA算法有两个优化算法 SLF 和 LLL: SLF:Small Label First 策略,设要加入的节点是j,队首元素为i,若dist(j)<dist(i),则将j插入队首,否则插入队 ...
随机推荐
- C++类的友元机制说明
下面给出C++类的友元机制说明(对类private.protected成员访问),需要注意的是,友元机制尽量不用或者少用,虽然它会提供某种程度的效率,但会带来数据安全性的问题. 类的友元 友元是C++ ...
- jq日期与时间戳互相转换
方法1:$.extend({ myTime: { CurTime: function () { return Date.parse(new Date()) / 1000; }, DateToUnix: ...
- C#中委托、匿名函数、Lambda表达式的一些个人理解
0x01定义一个委托,相当于定义一个可以存储方法的特殊变量类型 下面我们看具体的代码,通过代码更好理解 delegate void IntMethodInvoker(int x); 这行代码就是声明一 ...
- FreeBSD jail 折腾记(一)
创建jail目录 mkdir -p /usr/jail/ 放入基本系统 方案一 make buildworld #编译基本系统 make installworld DESTDIR=/usr/jail/ ...
- WPF 应用 - 拖拽窗体、控件
1. 拖拽窗体 使用 System.Windows.Window 自带的 DragMove() 方法即可识别窗体拖动. DragMove(); 2. 拖拽控件:复制.移动控件 <Grid> ...
- golang 实现两数组对应元素相除
func ArrayDivision(arr1 []float64,arr2 []float64) (arr3 []float64) { //两数组对应元素相除 for p:=0;p< len( ...
- ResNet的个人总结
ResNet可以说是我认真读过的第一篇paper,据师兄说读起来比较简单,没有复杂的数学公式,不过作为经典的网络结构还是有很多细节值得深究的.因为平时不太读英文文献,所以其实读的时候也有很多地方不是很 ...
- ch2_8_3求解回文序列问题(递归实现)
思路:回文序列中左右两边的值一定相等,所以可以将该问题分解为两边化为相同元素操作的次数和去掉两边相等元素后后剩下元素变成回文序列的操作次数. 题目: 如果一个数字序列逆置之后跟原序列是一样的就称这样的 ...
- 使用Vscode 开发调试 C/C++ 项目
需要安装的扩展 C/C++ 如果是远程 Linux上开发还需要安装 Remote Development 创建工作目录后,代码远程克隆... 省略.. 创建项目配置文件,主要的作用是代码智能提示,错误 ...
- ubuntu20.04开机显示recovering journal死机的解决方法
事发突然,在今天开机的时候无法进入登陆界面,一直卡在黑屏界面,屏幕上只显示几行代码,且任何按键都无法起作用 /dev/sdb2:recovering journal /dev/sdb2:Clearin ...