原题地址: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的更多相关文章

  1. SGU185 Two shortest(最小费用最大流/最大流)

    题目求一张图两条边不重复的最短路. 一开始我用费用流做. 源点到1连容量2费用0的边:所有边,连u到v和v到u容量1费用cost的边. 总共最多会增广两次,比较两次求得的费用,然后输出路径. 然而死M ...

  2. [LeetCode] Encode String with Shortest Length 最短长度编码字符串

    Given a non-empty string, encode the string such that its encoded length is the shortest. The encodi ...

  3. [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 ...

  4. [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 ...

  5. [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 ...

  6. [LeetCode] Shortest Word Distance 最短单词距离

    Given a list of words and two words word1 and word2, return the shortest distance between these two ...

  7. [LeetCode] Shortest Palindrome 最短回文串

    Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. ...

  8. 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 ...

  9. LeetCode 214 Shortest Palindrome

    214-Shortest Palindrome Given a string S, you are allowed to convert it to a palindrome by adding ch ...

随机推荐

  1. 详解AngularJS中的filter过滤器用法

    系统的学习了一下angularjs,发现angularjs的有些思想根php的模块smarty很像,例如数据绑定,filter.如果对smarty比较熟悉的话,学习angularjs会比较容易一点.这 ...

  2. json数据与字符串相互转化的例子

    json与字符串之间的转换,本文分享一个小例子.   json转成string[需要引用json2.js文件]:  var arr=[{id:'id',name:'Spring'},{id:'id2' ...

  3. Javascript倒计时页面跳转

    在js中实现页面定时跳转我们要使用setInterval或setTimeOut函数,还可以使用页面的meta实现. 例1: <script type="text/javascript& ...

  4. WPF后台更换背景图-Background

    Uri uri = new Uri("Images/BACK.gif", UriKind.Relative);BitmapImage bimg = new BitmapImage( ...

  5. shell自定义函数

    Linux中提供了很多内置的函数,但有时我们需要根据自己的需求来创建自定义函数.下面介绍一下关于shell编程中的自定义函数. 1.函数定义 function hello(){    echo &qu ...

  6. springmvc+json

    1.在写我的springmvc demo时,由于要向前台返回相关信息,于是设置了@ResponseBody,但是要把对象转换成json格式,我却没有在xml文件里配置,所以报如下错误:HttpMedi ...

  7. /****************** Attributes ********************/

    /*预定义字符属性的文本.如果钥匙不在字典,然后使用默认值,如下所述. */ 以下属性是IOS6的 NSVerticalGlyphFormAttributeName NS_AVAILABLE_IOS( ...

  8. 【BZOJ 1022】 [SHOI2008]小约翰的游戏John

    Description 小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有n堆石子,小约翰和他的哥哥轮流取石子,每个人取的时候,可以随意选择一堆石子,在这堆石子中取走任意多的石子,但不能一粒石子也不取 ...

  9. Xcode 向6.0以后版本添加iOS开发空白模板

    打开finder,找到应用程序,找到xcode 右键显示包内容.按照如下目录进行查找:Contents ▸ Developer ▸ Platforms ▸ iPhoneOS.platform ▸ De ...

  10. office安装不了 “windows installer 服务不能更新一个或多个受保护的windows文件”

    出现这种情况可能是系统中某些文件缺失了,一般发生于安装GHOST版或做过精简的系统 打开C:\WINDOWS\msagent 看看文件夹中内容是不是如下图所示: 再打开C:\Program Files ...