SGU185 - Two Shortest
原题地址:http://acm.sgu.ru/problem.php?contest=0&problem=185
题目大意:给出一个无向图,求出从 1 到 n 的两条没有相同边的最短路径(允许有重复点),要求输出具体路径,不存在则输出"No solution"。保证两点之间没有重边。
数据范围和限制:点数 2 <= N <= 400, 边长小于等于10000。时间限制 0.25s 内存限制 4M
题目分析:
这题应该算是经典题目了,半年之前第一遍写就没过,昨天复习图论时下定决心开始搞定这道题,结果无限WA,刚刚总算把它调对了。话说SGU我还没做过几道题呢(惭愧)……
题目首先要求最短路,而且两条路必须都是最短路,而不能是一条最短的和一条次短的。那我们不妨先求出从 1 出发的单源最短路,然后考察最短路中的最优子结构性质:即若从 1 到 i 的最短路上经过了点 j ,则必须要满足 dist[j] + map[j][i] == dist[i], 否则我们总能找到一条更短的路径。这样我们不妨直接把不满足以上性质的边全部删除就好了。
下一个要求是不能有重复边。我们可以以 1 为源点, n 为汇点,剩下所有边的容量设为 1,做一遍最大流,如果最大流大于等于 2则有可行解,写一个DFS输出流的路径就行了,否则说明无重叠最短路不存在,输出无解信息
//date 20140115
#include <cstdio>
#include <cstring> const int maxn = ;
const int maxm = ;
const int INF = 0x7F7F7F7F; inline int getint()
{
int ans(); char w = getchar();
while('' > w || '' < w)w = getchar();
while('' <= w && w <= '')
{
ans = ans * + w - '';
w = getchar();
}
return ans;
} inline int min(int a, int b){return a < b ? a : b;} int n, m;
int map[maxn][maxn]; struct edge
{
int u, v, c, next;
}E[maxm];
int a[maxn];
int nedge; inline void add(int u, int v, int c)
{
E[++nedge].u = u;
E[nedge].v = v;
E[nedge].c = c;
E[nedge].next = a[u];
a[u] = nedge;
} int dis[maxn];
inline void init()
{
static int q[maxn];
static int inQ[maxn];
memset(dis, 0x7F, sizeof dis);
memset(inQ, , sizeof inQ);
dis[] = ;
int l = , r = ; q[] = ; inQ[] = ;
while(l < r)
{
int x = q[(++l) % maxn];
for(int i = ; i <= n; ++i)
if(map[x][i] > && map[x][i] + dis[x] < dis[i])
{
dis[i] = map[x][i] + dis[x];
if(!inQ[i]){q[(++r) % maxn] = i; inQ[i] = ;}
}
inQ[x] = ;
} for(int i = ; i <= n; ++i)
for(int j = ; j <= n; ++j)
if((map[i][j] > ) && (dis[i] + map[i][j] > dis[j]))map[i][j] = ; nedge = ;
for(int i = ; i <= n; ++i)
for(int j = ; j <= n; ++j)
if(map[i][j] > )
{
add(i, j, );
add(j, i, );
}
} int now[maxn];
int lab[maxn]; inline int label()
{
static int q[maxn];
int l = , r = ;
memset(lab, 0xFF, sizeof lab);
q[] = ; lab[] = ;
while(l < r)
{
int x = q[++l];
for(int i = a[x]; i; i = E[i].next)
if(E[i].c > && lab[E[i].v] == -)
{
lab[E[i].v] = lab[x] + ;
q[++r] = E[i].v;
// now[x] = i;
}
}
return (lab[n] != -);
} inline int Dinic(int v, int f)
{
if(v == n)return f;
int w, res = ;
for(int i = now[v]; i; i = now[v] = E[i].next)
if((E[i].c > ) && (f > ) && (lab[v] + == lab[E[i].v]) && (w = Dinic(E[i].v, min(f, E[i].c))))
{
E[i].c -= w;
E[i ^ ].c += w;
f -= w;
res += w;
}
return res;
} inline int max_flow()
{
int ans = ;
for(int i = ; i <= n; ++i)now[i] = a[i];
while(label()){ans += Dinic(, INF);for(int i = ; i <= n; ++i)now[i] = a[i];}
return ans;
} void dfs(int v)
{
if(v == n)printf("%d\n", v);
for(int i = a[v]; i; i = E[i].next)if(E[i].c == && map[v][E[i].v] > && dis[v] + map[v][E[i].v] == dis[E[i].v])
{
printf("%d ", v); dfs(E[i].v); map[v][E[i].v] = ; return;
}
}
inline void output()
{
dfs(), dfs();
}
int main()
{
freopen("sgu185.in", "r", stdin);
freopen("sgu185.out", "w", stdout); n = getint(); m = getint();
memset(map, , sizeof map);
memset(a, , sizeof a);
memset(E, , sizeof E);
for(int i = ; i <= m; ++i)
{
int x, y, z;
x = getint(); y = getint(); z = getint();
map[x][y] = map[y][x] = z;
}
init();
int ans = max_flow();
if(ans < )printf("No solution\n");
else output();
return ;
}
代码说明:求最短路的时候我用的SPFA,使用邻接矩阵存储,删边之后重新建图使用邻接表,用Dinic求最大流最后DFS递归输出答案就行
一些心得和收获:昨天第一遍写的时候用了两个邻接表,但是SPFA忘记开滚动队列了,由于机房关门了回家之后也没细查。今早到学校之后重写了一遍Dijkstra版本的,但是Dijkstra好像写错了无限WA……之后该做SPFA(但还是邻接矩阵)终于查出没有滚动队列的问题,之后开始TLE on test33,才发现Dinic的当前弧优化没写好,后来改对了总算AC了,我也总算有了自己比较熟练的最大流模板了。今天一上来邻接表的范围算错了,算成了400 * 400 * 2(网络流反向边),结果被SGU内存限制卡的死死的,后来证明出最短路删边之后图就变成单向的了没必要 * 2。继续加油!
SGU185 - Two Shortest的更多相关文章
- SGU185 Two shortest(最小费用最大流/最大流)
题目求一张图两条边不重复的最短路. 一开始我用费用流做. 源点到1连容量2费用0的边:所有边,连u到v和v到u容量1费用cost的边. 总共最多会增广两次,比较两次求得的费用,然后输出路径. 然而死M ...
- [LeetCode] Encode String with Shortest Length 最短长度编码字符串
Given a non-empty string, encode the string such that its encoded length is the shortest. The encodi ...
- [LeetCode] Shortest Distance from All Buildings 建筑物的最短距离
You want to build a house on an empty land which reaches all buildings in the shortest amount of dis ...
- [LeetCode] Shortest Word Distance III 最短单词距离之三
This is a follow up of Shortest Word Distance. The only difference is now word1 could be the same as ...
- [LeetCode] Shortest Word Distance II 最短单词距离之二
This is a follow up of Shortest Word Distance. The only difference is now you are given the list of ...
- [LeetCode] Shortest Word Distance 最短单词距离
Given a list of words and two words word1 and word2, return the shortest distance between these two ...
- [LeetCode] Shortest Palindrome 最短回文串
Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. ...
- Leetcode: Encode String with Shortest Length && G面经
Given a non-empty string, encode the string such that its encoded length is the shortest. The encodi ...
- LeetCode 214 Shortest Palindrome
214-Shortest Palindrome Given a string S, you are allowed to convert it to a palindrome by adding ch ...
随机推荐
- 如何使用Git——(二)
8.首次安装git,然后要把创建好的仓库放到github上,首先,你要先做一些基本设置,继续设置吧~~. 在git黑框框中输入 ssh-keygen -t rsa -C "your ema ...
- [Linux]学习笔记(1)
说到Linux就不得不提UNIX,因为Linux是从UNIX系统发展来的,两系统极为相似,可以在UNIX操作系统上使用的功能都可以在Linux上使用,只可能有少许的差异: UNIX系统中所有的东西都是 ...
- jquery 获取 CheckBox 的状态
<td style="width:220px;vertical-align:central;"><input type="checkbox" ...
- Spark小课堂Week2 Hello Streaming
Spark小课堂Week2 Hello Streaming 我们是怎么进行数据处理的? 批量方式处理 目前最常采用的是批量方式处理,指非工作时间运行,定时或者事件触发.这种方式的好处是逻辑简单,不影响 ...
- Oracle RAC LoadBalance
LoadBalance 就是把负载平均的分配到集群中的各个节点,从而提高整体的吞吐能力. Oracle 10g RAC 提供了两种不同的方法来分散负载: 通过Connection Balancing, ...
- 关于hadoop2.4.2版本学习时遇到的问题
问题一:namenode启动失败 描述:在初始化后hadoop后,发现datanode启动失败,namenode则可以正常启动,如果把用户换成root权限,再次启动时,则namenode和datano ...
- random note
今天才慢慢意识到,什么才是学习,(以思考解决问题为驱动),埋头刷分只是方法,不是目的和原动力. 既然准备读研,就要慢慢去了解研究生的生活学习方式是什么样的,涉及到哪些方面. 读研之前要选好方向,但是现 ...
- 机器学习基石的泛化理论及VC维部分整理(第五讲)
第五讲 Training versus Testing 一.问题的提出 \(P_{\mathcal{D}}\left [ BAD \mathcal{D} \right ] \leq 2M \cd ...
- vs中的主题配置
比较讨厌vs的默认字体颜色及背景,代码看久了就受不了.不过自己手动配置的话还是比较麻烦的,这里有一个网站(http://studiostyl.es/)提供了很多主题,一般都是背景比较深色的,对眼睛比较 ...
- 1027: [JSOI2007]合金 - BZOJ
Description 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的原材料中铁铝锡的比重不同.然后,将每种原材料取出一定量,经过融解.混合,得到新的 ...