原先一直在做一道省赛题,由于题意错误理解成球最短路条数,误打误撞敲了最短路条数,又发现hdu3599(多校)求边不可重复最短路条数。下面说说俩种问题解法:

最短路条数:

求一个图一共一几条最短路径,思路:先从终点跑一边最短路,记录终点到到所有点最短距离(d【i】),然后从起点出发,dfs 按d[i]走(必是最短路径),一句话:我到终点的最短路条数=我的所有孩子到终点的最短路条数之和,这样只需一遍即可。这不知道是不是叫记忆化搜索?

边不可重复最短路径条数:(最短路+建新图之最大流)

hdu3599题意:求1-->n最短路条数,所有路径边不可重复。思路:边不可重复??!!转为流量的为1 的话,求最大流啊(以后切记该方法,不可重复问题转最大流)!于是:先跑一遍最短路(随便从起点还是终点),然后按老图中是最短路的边就在新图添加一条边,权为1,这样的话,从起点到终点跑最大流即为答案。

附代码:问题一:

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int n;
int e[100000][3];int head[2000];
int nume=0;
int d[2000];
const int inf =0x3f3f3f3f;
int vis[2000];
int inq[2000];
void adde(int a,int b,int w)
{
e[nume][0]=b;e[nume][1]=head[a];head[a]=nume;
e[nume++][2]=w;
e[nume][0]=a;e[nume][1]=head[b];head[b]=nume;
e[nume++][2]=w;
}
void spfa() //一遍求出终点到所有点的最短路长度d[i]。
{
queue<int>q;
int start;
start=n;
inq[start]=1;
q.push(start);
d[start]=0;
while(!q.empty())
{
int cur=q.front();
q.pop();
inq[cur]=0;
for(int i=head[cur];i!=-1;i=e[i][1])
{
int v=e[i][0];
if(d[cur]+e[i][2]<d[v])
{
d[v]=d[cur]+e[i][2];
if(!inq[v])
{
inq[v]=1;
q.push(v);
}
}
}
}
return ;
}
long long counted[2000]; //点i到终点有几条最短路
int nowd[2000]; //从原点出发当前所走的长度
long long dfs(int cur) //记忆化收索? 访问所有点一遍求出最短路条数,
{
if(cur==n)
return 1;
for(int i=head[cur];i!=-1;i=e[i][1])
{
int v=e[i][0];
if(nowd[cur]+e[i][2]+d[v]!=d[1]) //走这一步必需是最短的
continue;
if(!vis[v]) //没有走过
{
nowd[v]=nowd[cur]+e[i][2];
vis[v]=1;
counted[cur]+=dfs(v); //我所有孩子(是最短路径中)到目标的最短路之和为我到目标最短路
}
else
{
counted[cur]+=counted[v]; //该孩子最短路条数已经算出
}
}
return counted[cur];
}
int main()
{
int ta;
cin>>ta;
while(ta--)
{
scanf("%d",&n);
int aa,bb,cc;
for(int i=0;i<=n;i++)
{
head[i]=-1;
nowd[i]=d[i]=inf;
inq[i]=counted[i]=vis[i]=0;
}
nume=0;
while(~scanf("%d%d%d",&aa,&bb,&cc)&&(aa||bb||cc))
adde(aa,bb,cc);
spfa();
counted[n]=1;
nowd[1]=0;
vis[1]=1;
cout<<dfs(1)<<endl;
}
return 0;
}

问题2:

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int n;
int e[2260000][3];int head[1510];
int nume=0;
int d[1510];
const int inf =0x3f3f3f3f;
int inq[1510];
void adde(int a,int b,int w) //原图
{
e[nume][0]=b;e[nume][1]=head[a];head[a]=nume;
e[nume++][2]=w;
e[nume][0]=a;e[nume][1]=head[b];head[b]=nume;
e[nume++][2]=w;
}
int ee[2260000][3];int head2[1510]; //新图
void adde2(int a,int b)
{
ee[nume][0]=b;ee[nume][1]=head2[a];head2[a]=nume;
ee[nume++][2]=1;
ee[nume][0]=a;ee[nume][1]=head2[b];head2[b]=nume;
ee[nume++][2]=0;
}
void spfa() //求出终点到所有点的最短路长度d[i]。
{
queue<int>q;
int start;
start=n;
inq[start]=1;
q.push(start);
d[start]=0;
while(!q.empty())
{
int cur=q.front();
q.pop();
inq[cur]=0;
for(int i=head[cur];i!=-1;i=e[i][1])
{
int v=e[i][0];
if(d[cur]+e[i][2]<d[v])
{
d[v]=d[cur]+e[i][2];
if(!inq[v])
{
inq[v]=1;
q.push(v);
}
}
}
}
return ;
}
int vis[1510];int lev[1510];
int nowd[1510]; //从原点出发当前所走的长度
void dfs_getg(int cur) // 遍历一次老图获得新图
{
vis[cur]=1; //注意这里要标记访问,否则新图有重边!开始因为这个WA了好几遍!
if(cur==n)
return ;
for(int i=head[cur];i!=-1;i=e[i][1])
{
int v=e[i][0];
if(nowd[cur]+e[i][2]+d[v]!=d[1]) //走这一步必需是最短的
continue;
else //没有走过
{
nowd[v]=nowd[cur]+e[i][2];
adde2(cur,v);
if(!vis[v]) //这里在添加边之后方可进入,
dfs_getg(v);
}
}
return ;
} bool bfs() //dinic不解释
{
for(int i=0;i<=n;i++)
vis[i]=lev[i]=0;
queue<int>q;
q.push(1);
vis[1]=1;
while(!q.empty())
{
int cur=q.front();
q.pop();
for(int i=head2[cur];i!=-1;i=ee[i][1])
{
int v=ee[i][0];
if(!vis[v]&&ee[i][2]>0)
{
lev[v]=lev[cur]+1;
if(v==n) return 1;
vis[v]=1;
q.push(v);
}
}
}
return vis[n];
}
int dfs(int u,int minf)
{
if(u==n||minf==0)return minf;
int sumf=0,f;
for(int i=head2[u];i!=-1&&minf;i=ee[i][1])
{
int v=ee[i][0];
if(ee[i][2]>0&&lev[v]==lev[u]+1)
{
f=dfs(v,ee[i][2]<minf?ee[i][2]:minf);
ee[i][2]-=f;ee[i^1][2]+=f;
minf-=f;sumf+=f;
}
}
return sumf;
}
int dinic()
{
int sum=0;
while(bfs())
sum+=dfs(1,inf);
return sum;
}
int main()
{
int ta;
cin>>ta;
while(ta--)
{
scanf("%d",&n);
int aa,bb,cc;
for(int i=0;i<=n;i++)
{
head[i]=-1;
nowd[i]=d[i]=inf;
inq[i]=vis[i]=0;
}
nume=0;
while(~scanf("%d%d%d",&aa,&bb,&cc)&&(aa||bb||cc))
adde(aa,bb,cc);
if(n==1){cout<<0<<endl; continue;} // 1个点的时候要特判!!
spfa();
nume=0;
for(int i=0;i<=n;i++)
head2[i]=-1;
nowd[1]=0;
dfs_getg(1);
cout<<dinic()<<endl;
}
return 0;
}

附几组数据:

5

1 2 1

2 3 1

3 5 1

1 3 2

1 4 2

3 4 2

0 0 0

4

1 0 2

2 0 2

1 3 1

2 3 3

2 4 1

1 2 4

0 0 0

6

1 2 1

3 2 1

3 4 1

1 3 2

4 2 2

4 5 1

5 6 1

4 6 2

0 0 0

1

0 0 0

关于 最短路条数 和 边不可重复最短路条数问题 /hdu3599(边不可重复最短路)的更多相关文章

  1. OpenJudge计算概论-第二个重复出现的数

    /*======================================================================== 第二个重复出现的数 总时间限制: 1000ms 内 ...

  2. Openjudge-计算概论(A)-第二个重复出现的数

    描述: 给定一个正整数数组(元素的值都大于零),输出数组中第二个重复出现的正整数,如果没有,则输出字符串"NOT EXIST". 输入第一行为整数m,表示有m组数据.其后每组数据分 ...

  3. 一个int 数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它。能否只用一个额外数组和少量其它空间实现。

    一个int数组, 比如 array[],里面数据无任何限制,要求求出 所有这样的数array[i],其左边的数都小于等于它,右边的数都大于等于它.能否只用一个额外数组和少量其它空间实现. 分析:这题很 ...

  4. 17.从键盘上输入一个正整数n,请按照以下五行杨辉三角形的显示方式, 输出杨辉三角形的前n行。请采用循环控制语句来实现。 (三角形腰上的数为1,其他位置的数为其上一行相邻两个数之和。) 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1

    17.从键盘上输入一个正整数n,请按照以下五行杨辉三角形的显示方式, 输出杨辉三角形的前n行.请采用循环控制语句来实现. (三角形腰上的数为1,其他位置的数为其上一行相邻两个数之和.) 1 1 1 1 ...

  5. 转载:IIS 之 连接数、并发连接数、最大并发工作线程数、队列长度、最大工作进程数

    一.IIS连接数 一般购买过虚拟主机的朋友都熟悉购买时,会限制IIS连接数,顾名思义即为IIS服务器可以同时容纳客户请求的最高连接数,准确的说应该叫“IIS限制连接数”. 客户请求的连接内容包括: [ ...

  6. 【Python3练习题 025】 一个数,判断它是不是回文数。即12321是回文数,个位与万位相同,十位与千位相同

    [Python练习题 025] 一个5位数,判断它是不是回文数.即12321是回文数,个位与万位相同,十位与千位相同 x = input('请输入任意位数的数字:') if x == x[::-1]: ...

  7. 欧拉函数(小于或等于n的数中与n互质的数的数目)&& 欧拉函数线性筛法

    [欧拉函数] 在数论,对正整数n,欧拉函数是少于或等于n的数中与n互质的数的数目.此函数以其首名研究者欧拉命名,它又称为Euler’s totient function.φ函数.欧拉商数等. 例如φ( ...

  8. IIS 之 连接数、并发连接数、最大并发工作线程数、队列长度、最大工作进程数

    一.IIS连接数 一般购买过虚拟主机的朋友都熟悉购买时,会限制IIS连接数,顾名思义即为IIS服务器可以同时容纳客户请求的最高连接数,准确的说应该叫“IIS限制连接数”. 客户请求的连接内容包括: [ ...

  9. 12--c完数/最大公约数/最小公倍数/素数/回文数

    完数/最大公约数/最小公倍数/素数/回文数 2015-04-08 10:33 296人阅读 评论(0) 收藏 举报  分类: C/C++(60)  哈尔滨工业大学(8)  版权声明:本文为博主原创文章 ...

随机推荐

  1. 关于 QObject 类

    1.QObject类   简述 QObject类是所有Qt对象的基类. QObject是Qt对象模型的核心. 该模型的核心特征是称为信号和槽的对象通信机制. 您可以使用connect()将信号连接到槽 ...

  2. CAD交互绘制圆形云线批注(网页版)

    js中实现代码说明: 动态拖放时的绘制事件: function DoDynWorldDrawFun(dX,dY,pWorldDraw,pData) { //自定义实体的GUID标识符 var sGui ...

  3. 数据库-SQL语法:GROUP BY与HAVING

    注意:select 后的字段,必须要么包含在group by中,要么包含在having 后的聚合函数里. 1. GROUP BY 是分组查询, 一般 GROUP BY 是和聚合函数配合使用. grou ...

  4. POI把html写入word doc文件

    直接把Html文本写入到Word文件 获取查看页面的body内容和引用的css文件路径传入到后台. 把对应css文件的内容读取出来. 利用body内容和css文件的内容组成一个标准格式的Html文本. ...

  5. javase(5)_面向对象

    一.概述 1.面向对象是一种思想,让我们由执行者变成指挥者,执行者是面向过程,指挥者是面向对象.例如人开冰箱门,开冰箱门这个动作应该属于门而不是人,冰箱自己最清楚门应该怎么开,人只是调用了冰箱的这个动 ...

  6. javaEE(1)_web开发入门

    一.WEB开发的相关知识 1.WEB,在英语中web即表示网页的意思,它用于表示Internet主机上供外界访问的资源. Internet上供外界访问的Web资源分为: 静态web资源(如html 页 ...

  7. JS原型链(一)

    一.创建对象 // 第一种方式:字面量 var o1 = {name: 'o1'}; var o2 = new Object({name: 'o2'}); // 第二种方式:构造函数 var M = ...

  8. 【二分 贪心】bzoj3477: [Usaco2014 Mar]Sabotage

    科学二分姿势 Description Farmer John's arch-nemesis, Farmer Paul, has decided to sabotage Farmer John's mi ...

  9. [LUOGU] 1002 过河卒

    题目描述 棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为"马拦过 ...

  10. centOS下SVN安装和配置

    1>SVN服务器端文件可见问题 在平时使用SVN时候,一直以为在客户提交文件,那么在服务器对应的版本库下面就会有相同文件.在自己搭建后,发现提交到服务器端文件完全看不见.... 这是由于SVN服 ...